Refactor: create src/lib to reflect actual sharing of that code

This commit is contained in:
Paul Frazee 2022-11-22 12:02:31 -06:00
parent e858bb52de
commit c2a39d7c1f
21 changed files with 33 additions and 21 deletions

View file

@ -18,7 +18,7 @@ import {
enforceLen,
MAX_DISPLAY_NAME,
MAX_DESCRIPTION,
} from '../../lib/strings'
} from '../../../lib/strings'
import {AppBskyActorCreateScene} from '../../../third-party/api/index'
export const snapPoints = ['60%']

View file

@ -7,7 +7,11 @@ import {ErrorMessage} from '../util/ErrorMessage'
import {useStores} from '../../../state'
import {ProfileViewModel} from '../../../state/models/profile-view'
import {s, colors, gradients} from '../../lib/styles'
import {enforceLen, MAX_DISPLAY_NAME, MAX_DESCRIPTION} from '../../lib/strings'
import {
enforceLen,
MAX_DISPLAY_NAME,
MAX_DESCRIPTION,
} from '../../../lib/strings'
import * as Profile from '../../../third-party/api/src/client/types/app/bsky/actor/profile'
export const snapPoints = ['60%']

View file

@ -5,7 +5,7 @@ import {AtUri} from '../../../third-party/uri'
import {FontAwesomeIcon, Props} from '@fortawesome/react-native-fontawesome'
import {NotificationsViewItemModel} from '../../../state/models/notifications-view'
import {s, colors} from '../../lib/styles'
import {ago, pluralize} from '../../lib/strings'
import {ago, pluralize} from '../../../lib/strings'
import {UpIconSolid} from '../../lib/icons'
import {UserAvatar} from '../util/UserAvatar'
import {PostText} from '../post/PostText'

View file

@ -12,7 +12,7 @@ import {PostDropdownBtn} from '../util/DropdownBtn'
import Toast from '../util/Toast'
import {UserAvatar} from '../util/UserAvatar'
import {s, colors} from '../../lib/styles'
import {ago, pluralize} from '../../lib/strings'
import {ago, pluralize} from '../../../lib/strings'
import {useStores} from '../../../state'
import {PostMeta} from '../util/PostMeta'
import {PostCtrls} from '../util/PostCtrls'

View file

@ -17,7 +17,7 @@ import {
EditProfileModel,
InviteToSceneModel,
} from '../../../state/models/shell-ui'
import {pluralize} from '../../lib/strings'
import {pluralize} from '../../../lib/strings'
import {s, colors} from '../../lib/styles'
import {getGradient} from '../../lib/asset-gen'
import {MagnifyingGlassIcon} from '../../lib/icons'

View file

@ -13,7 +13,7 @@ import {IconProp} from '@fortawesome/fontawesome-svg-core'
import RootSiblings from 'react-native-root-siblings'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {colors} from '../../lib/styles'
import {toShareUrl} from '../../lib/strings'
import {toShareUrl} from '../../../lib/strings'
import {useStores} from '../../../state'
import {ConfirmModel} from '../../../state/models/shell-ui'
import {TABS_ENABLED} from '../../../build-flags'

View file

@ -4,7 +4,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {Link} from '../util/Link'
import {PostDropdownBtn} from '../util/DropdownBtn'
import {s} from '../../lib/styles'
import {ago} from '../../lib/strings'
import {ago} from '../../../lib/strings'
interface PostMetaOpts {
itemHref: string

View file

@ -1,151 +0,0 @@
import {AtUri} from '../../third-party/uri'
import {Entity} from '../../third-party/api/src/client/types/app/bsky/feed/post'
import {PROD_SERVICE} from '../../state'
export const MAX_DISPLAY_NAME = 64
export const MAX_DESCRIPTION = 256
export function pluralize(n: number, base: string, plural?: string): string {
if (n === 1) {
return base
}
if (plural) {
return plural
}
return base + 's'
}
export function makeRecordUri(
didOrName: string,
collection: string,
rkey: string,
) {
const urip = new AtUri(`at://host/`)
urip.host = didOrName
urip.collection = collection
urip.rkey = rkey
return urip.toString()
}
const MINUTE = 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
const MONTH = DAY * 30
const YEAR = DAY * 365
export function ago(date: number | string | Date): string {
let ts: number
if (typeof date === 'string') {
ts = Number(new Date(date))
} else if (date instanceof Date) {
ts = Number(date)
} else {
ts = date
}
const diffSeconds = Math.floor((Date.now() - ts) / 1e3)
if (diffSeconds < MINUTE) {
return `${diffSeconds}s`
} else if (diffSeconds < HOUR) {
return `${Math.floor(diffSeconds / MINUTE)}m`
} else if (diffSeconds < DAY) {
return `${Math.floor(diffSeconds / HOUR)}h`
} else if (diffSeconds < MONTH) {
return `${Math.floor(diffSeconds / DAY)}d`
} else if (diffSeconds < YEAR) {
return `${Math.floor(diffSeconds / MONTH)}mo`
} else {
return new Date(ts).toLocaleDateString()
}
}
export function extractEntities(
text: string,
knownHandles?: Set<string>,
): Entity[] | undefined {
let match
let ents: Entity[] = []
{
// mentions
const re = /(^|\s)(@)([a-zA-Z0-9\.-]+)(\b)/dg
while ((match = re.exec(text))) {
if (knownHandles && !knownHandles.has(match[3])) {
continue // not a known handle
}
ents.push({
type: 'mention',
value: match[3],
index: {
start: match.indices[2][0], // skip the (^|\s) but include the '@'
end: match.indices[3][1],
},
})
}
}
{
// links
const re = /(^|\s)(https?:\/\/[\S]+)(\b)/dg
while ((match = re.exec(text))) {
ents.push({
type: 'link',
value: match[2],
index: {
start: match.indices[1][0], // skip the (^|\s) but include the '@'
end: match.indices[2][1],
},
})
}
}
return ents.length > 0 ? ents : undefined
}
export function makeValidHandle(str: string): string {
if (str.length > 20) {
str = str.slice(0, 20)
}
str = str.toLowerCase()
return str.replace(/^[^a-z]+/g, '').replace(/[^a-z0-9-]/g, '')
}
export function createFullHandle(name: string, domain: string): string {
name = name.replace(/[\.]+$/, '')
domain = domain.replace(/^[\.]+/, '')
return `${name}.${domain}`
}
export function enforceLen(str: string, len: number): string {
str = str || ''
if (str.length > len) {
return str.slice(0, len)
}
return str
}
export function cleanError(str: string): string {
if (str.includes('Network request failed')) {
return 'Unable to connect. Please check your internet connection and try again.'
}
if (str.startsWith('Error: ')) {
return str.slice('Error: '.length)
}
return str
}
export function toNiceDomain(url: string): string {
try {
const urlp = new URL(url)
if (`https://${urlp.host}` === PROD_SERVICE) {
return 'Bluesky Social'
}
return urlp.host
} catch (e) {
return url
}
}
export function toShareUrl(url: string) {
if (!url.startsWith('https')) {
const urlp = new URL('https://bsky.app')
urlp.pathname = url
url = urlp.toString()
}
return url
}

View file

@ -16,7 +16,11 @@ import * as EmailValidator from 'email-validator'
import {observer} from 'mobx-react-lite'
import {Picker} from '../com/util/Picker'
import {s, colors} from '../lib/styles'
import {makeValidHandle, createFullHandle, toNiceDomain} from '../lib/strings'
import {
makeValidHandle,
createFullHandle,
toNiceDomain,
} from '../../lib/strings'
import {useStores, DEFAULT_SERVICE} from '../../state'
import {ServiceDescription} from '../../state/models/session'
import {ServerInputModel} from '../../state/models/shell-ui'

View file

@ -4,7 +4,7 @@ import {ViewHeader} from '../com/util/ViewHeader'
import {PostVotedBy as PostLikedByComponent} from '../com/post-thread/PostVotedBy'
import {ScreenParams} from '../routes'
import {useStores} from '../../state'
import {makeRecordUri} from '../lib/strings'
import {makeRecordUri} from '../../lib/strings'
export const PostDownvotedBy = ({navIdx, visible, params}: ScreenParams) => {
const store = useStores()

View file

@ -4,7 +4,7 @@ import {ViewHeader} from '../com/util/ViewHeader'
import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
import {ScreenParams} from '../routes'
import {useStores} from '../../state'
import {makeRecordUri} from '../lib/strings'
import {makeRecordUri} from '../../lib/strings'
export const PostRepostedBy = ({navIdx, visible, params}: ScreenParams) => {
const store = useStores()

View file

@ -1,6 +1,6 @@
import React, {useEffect, useMemo, useState} from 'react'
import {View} from 'react-native'
import {makeRecordUri} from '../lib/strings'
import {makeRecordUri} from '../../lib/strings'
import {ViewHeader} from '../com/util/ViewHeader'
import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread'
import {PostThreadViewModel} from '../../state/models/post-thread-view'

View file

@ -4,7 +4,7 @@ import {ViewHeader} from '../com/util/ViewHeader'
import {PostVotedBy as PostLikedByComponent} from '../com/post-thread/PostVotedBy'
import {ScreenParams} from '../routes'
import {useStores} from '../../state'
import {makeRecordUri} from '../lib/strings'
import {makeRecordUri} from '../../lib/strings'
export const PostUpvotedBy = ({navIdx, visible, params}: ScreenParams) => {
const store = useStores()

View file

@ -21,7 +21,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import Swipeable from 'react-native-gesture-handler/Swipeable'
import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles'
import {toShareUrl} from '../../lib/strings'
import {toShareUrl} from '../../../lib/strings'
import {match} from '../../routes'
const TAB_HEIGHT = 42

View file

@ -37,6 +37,7 @@ import {MainMenu} from './MainMenu'
import {TabsSelector} from './TabsSelector'
import {Composer} from './Composer'
import {s, colors} from '../../lib/styles'
import {clamp} from '../../../lib/numbers'
import {
GridIcon,
GridIconSolid,