mirror of https://github.com/tooot-app/app
Updates
This commit is contained in:
parent
1072d88191
commit
b8aa402c99
|
@ -1,15 +1,3 @@
|
||||||
node_modules/
|
|
||||||
.expo/
|
|
||||||
.expo-shared/
|
|
||||||
npm-debug.*
|
|
||||||
*.jks
|
|
||||||
*.p8
|
|
||||||
*.p12
|
|
||||||
*.key
|
|
||||||
*.mobileprovision
|
|
||||||
*.orig.*
|
|
||||||
web-build/
|
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
@ -17,46 +5,13 @@ web-build/
|
||||||
coverage/
|
coverage/
|
||||||
builds/
|
builds/
|
||||||
|
|
||||||
fastlane/id_rsa
|
|
||||||
|
|
||||||
# @generated expo-cli sync-28e2ab0e9ece60556eaf932abe52d017ec33db50
|
# @generated expo-cli sync-28e2ab0e9ece60556eaf932abe52d017ec33db50
|
||||||
# The following patterns were generated by expo-cli
|
# The following patterns were generated by expo-cli
|
||||||
|
|
||||||
# OSX
|
# OSX
|
||||||
#
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Xcode
|
|
||||||
#
|
|
||||||
build/
|
|
||||||
*.pbxuser
|
|
||||||
!default.pbxuser
|
|
||||||
*.mode1v3
|
|
||||||
!default.mode1v3
|
|
||||||
*.mode2v3
|
|
||||||
!default.mode2v3
|
|
||||||
*.perspectivev3
|
|
||||||
!default.perspectivev3
|
|
||||||
xcuserdata
|
|
||||||
*.xccheckout
|
|
||||||
*.moved-aside
|
|
||||||
DerivedData
|
|
||||||
*.hmap
|
|
||||||
*.ipa
|
|
||||||
*.xcuserstate
|
|
||||||
project.xcworkspace
|
|
||||||
|
|
||||||
# Android/IntelliJ
|
|
||||||
#
|
|
||||||
build/
|
|
||||||
.idea
|
|
||||||
.gradle
|
|
||||||
local.properties
|
|
||||||
*.iml
|
|
||||||
*.hprof
|
|
||||||
|
|
||||||
# node.js
|
# node.js
|
||||||
#
|
|
||||||
node_modules/
|
node_modules/
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
@ -67,25 +22,12 @@ buck-out/
|
||||||
*.keystore
|
*.keystore
|
||||||
!debug.keystore
|
!debug.keystore
|
||||||
|
|
||||||
# fastlane
|
|
||||||
#
|
|
||||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
|
||||||
# screenshots whenever they are needed.
|
|
||||||
# For more information about the recommended setup visit:
|
|
||||||
# https://docs.fastlane.tools/best-practices/source-control/
|
|
||||||
|
|
||||||
*/fastlane/report.xml
|
|
||||||
*/fastlane/Preview.html
|
|
||||||
*/fastlane/screenshots
|
|
||||||
|
|
||||||
# Bundle artifacts
|
# Bundle artifacts
|
||||||
*.jsbundle
|
*.jsbundle
|
||||||
|
|
||||||
# CocoaPods
|
|
||||||
/ios/Pods/
|
|
||||||
|
|
||||||
# Expo
|
# Expo
|
||||||
.expo/*
|
.expo/*
|
||||||
|
.expo-shared/*
|
||||||
web-build/
|
web-build/
|
||||||
|
|
||||||
# @end expo-cli
|
# @end expo-cli
|
|
@ -0,0 +1,6 @@
|
||||||
|
build/
|
||||||
|
.idea
|
||||||
|
.gradle
|
||||||
|
local.properties
|
||||||
|
*.iml
|
||||||
|
*.hprof
|
|
@ -7,7 +7,7 @@ export default (): ExpoConfig => ({
|
||||||
slug: 'tooot',
|
slug: 'tooot',
|
||||||
privacy: 'hidden',
|
privacy: 'hidden',
|
||||||
sdkVersion: '40.0.0',
|
sdkVersion: '40.0.0',
|
||||||
version: '0.1.0',
|
version: '0.8',
|
||||||
platforms: ['ios', 'android'],
|
platforms: ['ios', 'android'],
|
||||||
orientation: 'portrait',
|
orientation: 'portrait',
|
||||||
userInterfaceStyle: 'automatic',
|
userInterfaceStyle: 'automatic',
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
*.key
|
||||||
|
*.jks
|
||||||
|
*.p8
|
||||||
|
*.p12
|
||||||
|
|
||||||
|
/report.xml
|
||||||
|
Preview.html
|
||||||
|
screenshots
|
|
@ -0,0 +1 @@
|
||||||
|
app_identifier "com.xmflsct.app.tooot"
|
|
@ -1,28 +1,12 @@
|
||||||
$ExpoSDK = '40.0.0'
|
$ExpoSDK = '40.0.0'
|
||||||
$ExpoRelease = '40'
|
$NativeVersion = '210201' # Update when there is native module change
|
||||||
|
|
||||||
fastlane_version '2.172.0'
|
fastlane_version '2.172.0'
|
||||||
|
|
||||||
platform :ios do
|
platform :ios do
|
||||||
desc 'Build and deploy'
|
desc 'Build and deploy'
|
||||||
private_lane :build do |options|
|
private_lane :build do |options|
|
||||||
branch = 'RELEASE-TYPE'.gsub('RELEASE', $ExpoRelease).gsub('TYPE', options[:type])
|
branch = 'NATIVEVERSION-TYPE'.gsub('NATIVEVERSION', $NativeVersion).gsub('TYPE', options[:type])
|
||||||
|
|
||||||
case options[:type]
|
|
||||||
when 'staging', 'production'
|
|
||||||
ensure_git_branch(
|
|
||||||
branch: branch
|
|
||||||
)
|
|
||||||
ensure_git_status_clean
|
|
||||||
build_number = Time.new.strftime('%y%m%d%k')
|
|
||||||
increment_build_number build_number: build_number
|
|
||||||
end
|
|
||||||
|
|
||||||
match(
|
|
||||||
type: options[:type],
|
|
||||||
readonly: true
|
|
||||||
)
|
|
||||||
|
|
||||||
set_info_plist_value(
|
set_info_plist_value(
|
||||||
path: './ios/tooot/Supporting/Expo.plist',
|
path: './ios/tooot/Supporting/Expo.plist',
|
||||||
key: 'EXUpdatesSDKVersion',
|
key: 'EXUpdatesSDKVersion',
|
||||||
|
@ -34,6 +18,25 @@ platform :ios do
|
||||||
value: branch
|
value: branch
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case options[:type]
|
||||||
|
when 'staging', 'production'
|
||||||
|
ensure_git_branch(
|
||||||
|
branch: options[:type]
|
||||||
|
)
|
||||||
|
ensure_git_status_clean
|
||||||
|
increment_build_number(
|
||||||
|
build_number: $NativeVersion
|
||||||
|
)
|
||||||
|
app_store_connect_api_key(
|
||||||
|
key_filepath: "appstore.p8"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
match(
|
||||||
|
type: options[:type],
|
||||||
|
readonly: true
|
||||||
|
)
|
||||||
|
|
||||||
case options[:type]
|
case options[:type]
|
||||||
when 'development'
|
when 'development'
|
||||||
build_ios_app(
|
build_ios_app(
|
||||||
|
@ -41,13 +44,10 @@ platform :ios do
|
||||||
silent: true,
|
silent: true,
|
||||||
include_bitcode: true,
|
include_bitcode: true,
|
||||||
workspace: './ios/tooot.xcworkspace',
|
workspace: './ios/tooot.xcworkspace',
|
||||||
output_directory: './build/ios',
|
|
||||||
output_name: 'development',
|
|
||||||
export_method: 'development'
|
export_method: 'development'
|
||||||
)
|
)
|
||||||
install_on_device(
|
install_on_device(
|
||||||
skip_wifi: true,
|
skip_wifi: true
|
||||||
ipa: './build/ios/development.ipa'
|
|
||||||
)
|
)
|
||||||
when 'staging'
|
when 'staging'
|
||||||
build_ios_app(
|
build_ios_app(
|
||||||
|
@ -55,8 +55,8 @@ platform :ios do
|
||||||
workspace: './ios/tooot.xcworkspace'
|
workspace: './ios/tooot.xcworkspace'
|
||||||
)
|
)
|
||||||
upload_to_testflight(
|
upload_to_testflight(
|
||||||
api_key: '{"key_id": "KEY_ID", "issuer_id": "ISSUER_ID", "key_filepath": "appstore.p8"}'.gsub('KEY_ID', ENV['APP_STORE_KEY_ID']).gsub('ISSUER_ID', ENV['APP_STORE_ISSUER_ID']),
|
skip_submission: true,
|
||||||
skip_submission: true
|
notify_external_testers: false
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
git_url(ENV('MATCH_GIT_REPO'))
|
|
||||||
git_user_email("me@xmflsct.com")
|
git_user_email("me@xmflsct.com")
|
||||||
git_private_key("./id_rsa")
|
git_private_key("./github.key")
|
||||||
|
|
||||||
storage_mode("git")
|
storage_mode("git")
|
||||||
|
|
||||||
type("development")
|
|
||||||
|
|
||||||
app_identifier(["com.xmflsct.app.tooot"])
|
|
||||||
username(ENV['APP_STORE_EMAIL'])
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<testsuites>
|
|
||||||
<testsuite name="fastlane.lanes">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: Verifying fastlane version" time="0.000454">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: Switch to ios build lane" time="0.00019">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: match" time="3.907079">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: set_info_plist_value" time="0.003664">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="4: set_info_plist_value" time="0.002893">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="5: build_ios_app" time="557.460706">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="6: install_on_device" time="3.305225">
|
|
||||||
|
|
||||||
</testcase>
|
|
||||||
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/Pods/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
build/
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata
|
||||||
|
*.xccheckout
|
||||||
|
*.moved-aside
|
||||||
|
DerivedData
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.xcuserstate
|
||||||
|
project.xcworkspace
|
|
@ -9,7 +9,7 @@
|
||||||
<key>EXUpdatesLaunchWaitMs</key>
|
<key>EXUpdatesLaunchWaitMs</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>EXUpdatesReleaseChannel</key>
|
<key>EXUpdatesReleaseChannel</key>
|
||||||
<string>40-development</string>
|
<string>210201-development</string>
|
||||||
<key>EXUpdatesSDKVersion</key>
|
<key>EXUpdatesSDKVersion</key>
|
||||||
<string>40.0.0</string>
|
<string>40.0.0</string>
|
||||||
<key>EXUpdatesURL</key>
|
<key>EXUpdatesURL</key>
|
||||||
|
|
|
@ -13,61 +13,59 @@ export interface Props {
|
||||||
fontBold?: boolean
|
fontBold?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const ParseEmojis: React.FC<Props> = ({
|
const ParseEmojis = React.memo(
|
||||||
content,
|
({ content, emojis, size = 'M', fontBold = false }: Props) => {
|
||||||
emojis,
|
const { mode, theme } = useTheme()
|
||||||
size = 'M',
|
const styles = useMemo(() => {
|
||||||
fontBold = false
|
return StyleSheet.create({
|
||||||
}) => {
|
text: {
|
||||||
const { mode, theme } = useTheme()
|
color: theme.primary,
|
||||||
const styles = useMemo(() => {
|
...StyleConstants.FontStyle[size],
|
||||||
return StyleSheet.create({
|
...(fontBold && { fontWeight: StyleConstants.Font.Weight.Bold })
|
||||||
text: {
|
},
|
||||||
color: theme.primary,
|
image: {
|
||||||
...StyleConstants.FontStyle[size],
|
width: StyleConstants.Font.Size[size],
|
||||||
...(fontBold && { fontWeight: StyleConstants.Font.Weight.Bold })
|
height: StyleConstants.Font.Size[size],
|
||||||
},
|
transform: [{ translateY: size === 'L' ? -3 : -1 }]
|
||||||
image: {
|
}
|
||||||
width: StyleConstants.Font.Size[size],
|
})
|
||||||
height: StyleConstants.Font.Size[size],
|
}, [mode])
|
||||||
transform: [{ translateY: size === 'L' ? -3 : -1 }]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, [mode])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text style={styles.text}>
|
<Text style={styles.text}>
|
||||||
{emojis ? (
|
{emojis ? (
|
||||||
content
|
content
|
||||||
.split(regexEmoji)
|
.split(regexEmoji)
|
||||||
.filter(f => f)
|
.filter(f => f)
|
||||||
.map((str, i) => {
|
.map((str, i) => {
|
||||||
if (str.match(regexEmoji)) {
|
if (str.match(regexEmoji)) {
|
||||||
const emojiShortcode = str.split(regexEmoji)[1]
|
const emojiShortcode = str.split(regexEmoji)[1]
|
||||||
const emojiIndex = emojis.findIndex(emoji => {
|
const emojiIndex = emojis.findIndex(emoji => {
|
||||||
return emojiShortcode === `:${emoji.shortcode}:`
|
return emojiShortcode === `:${emoji.shortcode}:`
|
||||||
})
|
})
|
||||||
return emojiIndex === -1 ? (
|
return emojiIndex === -1 ? (
|
||||||
<Text key={i}>{emojiShortcode}</Text>
|
<Text key={i}>{emojiShortcode}</Text>
|
||||||
) : (
|
) : (
|
||||||
<Text key={i}>
|
<Text key={i}>
|
||||||
{/* When emoji starts a paragraph, lineHeight will break */}
|
{/* When emoji starts a paragraph, lineHeight will break */}
|
||||||
{i === 0 ? <Text> </Text> : null}
|
{i === 0 ? <Text> </Text> : null}
|
||||||
<FastImage
|
<FastImage
|
||||||
source={{ uri: emojis[emojiIndex].url }}
|
source={{ uri: emojis[emojiIndex].url }}
|
||||||
style={styles.image}
|
style={styles.image}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return <Text key={i}>{str}</Text>
|
return <Text key={i}>{str}</Text>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
) : (
|
) : (
|
||||||
<Text>{content}</Text>
|
<Text>{content}</Text>
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
(prev, next) => prev.content === next.content
|
||||||
|
)
|
||||||
|
|
||||||
export default React.memo(ParseEmojis, () => true)
|
export default ParseEmojis
|
||||||
|
|
|
@ -30,8 +30,8 @@ const renderNode = ({
|
||||||
theme: any
|
theme: any
|
||||||
node: any
|
node: any
|
||||||
index: number
|
index: number
|
||||||
size: 'M' | 'L'
|
size: 'S' | 'M' | 'L'
|
||||||
navigation: StackNavigationProp<Nav.LocalStackParamList>
|
navigation: StackNavigationProp<Nav.TabLocalStackParamList>
|
||||||
mentions?: Mastodon.Mention[]
|
mentions?: Mastodon.Mention[]
|
||||||
tags?: Mastodon.Tag[]
|
tags?: Mastodon.Tag[]
|
||||||
showFullLink: boolean
|
showFullLink: boolean
|
||||||
|
@ -145,7 +145,7 @@ const renderNode = ({
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
content: string
|
content: string
|
||||||
size?: 'M' | 'L'
|
size?: 'S' | 'M' | 'L'
|
||||||
emojis?: Mastodon.Emoji[]
|
emojis?: Mastodon.Emoji[]
|
||||||
mentions?: Mastodon.Mention[]
|
mentions?: Mastodon.Mention[]
|
||||||
tags?: Mastodon.Tag[]
|
tags?: Mastodon.Tag[]
|
||||||
|
@ -167,7 +167,7 @@ const ParseHTML: React.FC<Props> = ({
|
||||||
disableDetails = false
|
disableDetails = false
|
||||||
}) => {
|
}) => {
|
||||||
const navigation = useNavigation<
|
const navigation = useNavigation<
|
||||||
StackNavigationProp<Nav.LocalStackParamList>
|
StackNavigationProp<Nav.TabLocalStackParamList>
|
||||||
>()
|
>()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
|
|
|
@ -82,11 +82,10 @@ const Timeline: React.FC<Props> = ({
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = navigation.addListener('focus', props => {
|
const unsubscribe = navigation.addListener('focus', props => {
|
||||||
if (props.target && props.target.includes('Screen-Notifications-Root')) {
|
if (props.target && props.target.includes('Tab-Notifications-Root')) {
|
||||||
if (flattenData.length) {
|
if (flattenData.length) {
|
||||||
dispatch(
|
dispatch(
|
||||||
localUpdateNotification({
|
localUpdateNotification({
|
||||||
unread: false,
|
|
||||||
latestTime: (flattenData[0] as Mastodon.Notification).created_at
|
latestTime: (flattenData[0] as Mastodon.Notification).created_at
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,6 +47,6 @@ export default {
|
||||||
heading: 'Help us improve',
|
heading: 'Help us improve',
|
||||||
description: 'Collecting only non-user relative usage'
|
description: 'Collecting only non-user relative usage'
|
||||||
},
|
},
|
||||||
version: 'Version v{{version}}'
|
version: 'Version v{{version}} ({{releaseChannel}})'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,6 @@ export default {
|
||||||
heading: '帮助我们改进',
|
heading: '帮助我们改进',
|
||||||
description: '收集不与用户相关联的使用信息'
|
description: '收集不与用户相关联的使用信息'
|
||||||
},
|
},
|
||||||
version: '版本 v{{version}}'
|
version: '版本 v{{version}} ({{releaseChannel}})'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ const ScreenTabs: React.FC<ScreenTabsProp> = ({ navigation }) => {
|
||||||
}),
|
}),
|
||||||
[localActiveIndex, localAccount]
|
[localActiveIndex, localAccount]
|
||||||
)
|
)
|
||||||
const tabNavigatorTabBarOptions = useMemo(
|
const tabBarOptions = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
activeTintColor: theme.primary,
|
activeTintColor: theme.primary,
|
||||||
inactiveTintColor:
|
inactiveTintColor:
|
||||||
|
@ -100,7 +100,7 @@ const ScreenTabs: React.FC<ScreenTabsProp> = ({ navigation }) => {
|
||||||
}),
|
}),
|
||||||
[theme, localActiveIndex]
|
[theme, localActiveIndex]
|
||||||
)
|
)
|
||||||
const tabScreenLocalListeners = useCallback(
|
const localListeners = useCallback(
|
||||||
() => ({
|
() => ({
|
||||||
tabPress: (e: any) => {
|
tabPress: (e: any) => {
|
||||||
if (!(localActiveIndex !== null)) {
|
if (!(localActiveIndex !== null)) {
|
||||||
|
@ -110,7 +110,7 @@ const ScreenTabs: React.FC<ScreenTabsProp> = ({ navigation }) => {
|
||||||
}),
|
}),
|
||||||
[localActiveIndex]
|
[localActiveIndex]
|
||||||
)
|
)
|
||||||
const tabScreenComposeListeners = useMemo(
|
const composeListeners = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
tabPress: (e: any) => {
|
tabPress: (e: any) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -122,8 +122,8 @@ const ScreenTabs: React.FC<ScreenTabsProp> = ({ navigation }) => {
|
||||||
}),
|
}),
|
||||||
[localActiveIndex]
|
[localActiveIndex]
|
||||||
)
|
)
|
||||||
const tabScreenComposeComponent = useCallback(() => null, [])
|
const composeComponent = useCallback(() => null, [])
|
||||||
const tabScreenNotificationsListeners = useCallback(
|
const notificationsListeners = useCallback(
|
||||||
() => ({
|
() => ({
|
||||||
tabPress: (e: any) => {
|
tabPress: (e: any) => {
|
||||||
if (!(localActiveIndex !== null)) {
|
if (!(localActiveIndex !== null)) {
|
||||||
|
@ -144,66 +144,67 @@ const ScreenTabs: React.FC<ScreenTabsProp> = ({ navigation }) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const prevNotification = useSelector(getLocalNotification)
|
const prevNotification = useSelector(getLocalNotification)
|
||||||
useEffect(() => {
|
const notificationsOptions = useMemo(() => {
|
||||||
if (queryNotification.data?.pages) {
|
const badge = {
|
||||||
const flattenData = queryNotification.data.pages.flatMap(d => [...d])
|
show: {
|
||||||
const latestNotificationTime = flattenData.length
|
tabBarBadge: '',
|
||||||
? (flattenData[0] as Mastodon.Notification).created_at
|
tabBarBadgeStyle: {
|
||||||
: undefined
|
transform: [{ scale: 0.5 }],
|
||||||
|
backgroundColor: theme.red
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
tabBarBadgeStyle: {
|
||||||
|
transform: [{ scale: 0.5 }],
|
||||||
|
backgroundColor: theme.red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const flattenData = queryNotification.data?.pages.flatMap(d => [...d])
|
||||||
|
const latestNotificationTime = flattenData?.length
|
||||||
|
? (flattenData[0] as Mastodon.Notification).created_at
|
||||||
|
: undefined
|
||||||
|
|
||||||
if (!prevNotification || !prevNotification.latestTime) {
|
if (prevNotification?.latestTime) {
|
||||||
dispatch(localUpdateNotification({ unread: false }))
|
if (
|
||||||
} else if (
|
|
||||||
latestNotificationTime &&
|
latestNotificationTime &&
|
||||||
new Date(prevNotification.latestTime) < new Date(latestNotificationTime)
|
new Date(prevNotification.latestTime) < new Date(latestNotificationTime)
|
||||||
) {
|
) {
|
||||||
dispatch(
|
return badge.show
|
||||||
localUpdateNotification({
|
} else {
|
||||||
unread: true,
|
return badge.hide
|
||||||
latestTime: latestNotificationTime
|
}
|
||||||
})
|
} else {
|
||||||
)
|
if (latestNotificationTime) {
|
||||||
|
return badge.show
|
||||||
|
} else {
|
||||||
|
return badge.hide
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [queryNotification.data?.pages])
|
}, [prevNotification, queryNotification.data?.pages])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Navigator
|
<Tab.Navigator
|
||||||
initialRouteName={localActiveIndex !== null ? 'Tab-Local' : 'Tab-Me'}
|
initialRouteName={localActiveIndex !== null ? 'Tab-Local' : 'Tab-Me'}
|
||||||
screenOptions={screenOptions}
|
screenOptions={screenOptions}
|
||||||
tabBarOptions={tabNavigatorTabBarOptions}
|
tabBarOptions={tabBarOptions}
|
||||||
>
|
>
|
||||||
<Tab.Screen
|
<Tab.Screen
|
||||||
name='Tab-Local'
|
name='Tab-Local'
|
||||||
component={TabLocal}
|
component={TabLocal}
|
||||||
listeners={tabScreenLocalListeners}
|
listeners={localListeners}
|
||||||
/>
|
/>
|
||||||
<Tab.Screen name='Tab-Public' component={TabPublic} />
|
<Tab.Screen name='Tab-Public' component={TabPublic} />
|
||||||
<Tab.Screen
|
<Tab.Screen
|
||||||
name='Tab-Compose'
|
name='Tab-Compose'
|
||||||
component={tabScreenComposeComponent}
|
component={composeComponent}
|
||||||
listeners={tabScreenComposeListeners}
|
listeners={composeListeners}
|
||||||
/>
|
/>
|
||||||
<Tab.Screen
|
<Tab.Screen
|
||||||
name='Tab-Notifications'
|
name='Tab-Notifications'
|
||||||
component={TabNotifications}
|
component={TabNotifications}
|
||||||
listeners={tabScreenNotificationsListeners}
|
listeners={notificationsListeners}
|
||||||
options={
|
options={notificationsOptions}
|
||||||
prevNotification && prevNotification.unread
|
|
||||||
? {
|
|
||||||
tabBarBadge: '',
|
|
||||||
tabBarBadgeStyle: {
|
|
||||||
transform: [{ scale: 0.5 }],
|
|
||||||
backgroundColor: theme.red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
tabBarBadgeStyle: {
|
|
||||||
transform: [{ scale: 0.5 }],
|
|
||||||
backgroundColor: theme.red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Tab.Screen name='Tab-Me' component={TabMe} />
|
<Tab.Screen name='Tab-Me' component={TabMe} />
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
|
|
|
@ -29,7 +29,10 @@ const SettingsAnalytics: React.FC = () => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.version, { color: theme.secondary }]}>
|
<Text style={[styles.version, { color: theme.secondary }]}>
|
||||||
{t('content.version', { version: Constants.manifest.version })}
|
{t('content.version', {
|
||||||
|
version: Constants.manifest.version,
|
||||||
|
releaseChannel: Constants.manifest.releaseChannel || 'dev'
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
</MenuContainer>
|
</MenuContainer>
|
||||||
)
|
)
|
||||||
|
|
|
@ -75,7 +75,7 @@ const AccountInformation: React.FC<Props> = ({ account, myInfo = false }) => {
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
base: {
|
base: {
|
||||||
marginTop: -StyleConstants.Spacing.Global.PagePadding * 3,
|
marginTop: -StyleConstants.Avatar.L / 2,
|
||||||
padding: StyleConstants.Spacing.Global.PagePadding
|
padding: StyleConstants.Spacing.Global.PagePadding
|
||||||
},
|
},
|
||||||
avatarAndActions: {
|
avatarAndActions: {
|
||||||
|
|
|
@ -25,7 +25,7 @@ const AccountInformationFields = React.memo(
|
||||||
>
|
>
|
||||||
<ParseHTML
|
<ParseHTML
|
||||||
content={field.name}
|
content={field.name}
|
||||||
size={'M'}
|
size={'S'}
|
||||||
emojis={account.emojis}
|
emojis={account.emojis}
|
||||||
showFullLink
|
showFullLink
|
||||||
numberOfLines={5}
|
numberOfLines={5}
|
||||||
|
@ -42,7 +42,7 @@ const AccountInformationFields = React.memo(
|
||||||
<View style={styles.fieldRight}>
|
<View style={styles.fieldRight}>
|
||||||
<ParseHTML
|
<ParseHTML
|
||||||
content={field.value}
|
content={field.value}
|
||||||
size={'M'}
|
size={'S'}
|
||||||
emojis={account.emojis}
|
emojis={account.emojis}
|
||||||
showFullLink
|
showFullLink
|
||||||
numberOfLines={5}
|
numberOfLines={5}
|
||||||
|
|
|
@ -20,7 +20,6 @@ export type InstanceLocal = {
|
||||||
preferences: Mastodon.Preferences
|
preferences: Mastodon.Preferences
|
||||||
}
|
}
|
||||||
notification: {
|
notification: {
|
||||||
unread: boolean
|
|
||||||
latestTime?: Mastodon.Notification['created_at']
|
latestTime?: Mastodon.Notification['created_at']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +114,7 @@ export const localAddInstance = createAsyncThunk(
|
||||||
preferences
|
preferences
|
||||||
},
|
},
|
||||||
notification: {
|
notification: {
|
||||||
unread: false
|
latestTime: undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -203,10 +202,8 @@ const instancesSlice = createSlice({
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<Partial<InstanceLocal['notification']>>
|
action: PayloadAction<Partial<InstanceLocal['notification']>>
|
||||||
) => {
|
) => {
|
||||||
state.local.instances[state.local.activeIndex!].notification = {
|
state.local.instances[state.local.activeIndex!].notification =
|
||||||
...state.local.instances[state.local.activeIndex!].notification,
|
action.payload
|
||||||
...action.payload
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
remoteUpdate: (
|
remoteUpdate: (
|
||||||
state,
|
state,
|
||||||
|
|
Loading…
Reference in New Issue