diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9ad7d0c49..c052bc551 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -325,8 +325,8 @@ PODS: - React-Core - react-native-receive-sharing-intent (1.0.4): - React - - react-native-restart (0.0.17): - - React + - react-native-restart (0.0.23): + - React-Core - react-native-safe-area-context (3.1.9): - React-Core - react-native-splash-screen (3.2.0): @@ -731,7 +731,7 @@ SPEC CHECKSUMS: react-native-netinfo: 30fb89fa913c342be82a887b56e96be6d71201dd react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846 react-native-receive-sharing-intent: feba0a332a07977549a85aa58b496eb44368366a - react-native-restart: d19a0f8d053d065fe64cd2baebb6487111c77149 + react-native-restart: aaad36f3ed7031daac3565f4a79d67e4f3884a50 react-native-safe-area-context: b6e0e284002381d2ff29fa4fff42b4d8282e3c94 react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865 react-native-udp: ff9d13e523f2b58e6bc5d4d32321ac60671b5dc9 @@ -772,4 +772,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 9c48318ea254e2c78005a7a0c2d8bfc14ddd783d -COCOAPODS: 1.10.1 +COCOAPODS: 1.11.2 diff --git a/package.json b/package.json index 7a7fda773..3fd08b9a7 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dependencies": { "@babel/runtime": "^7.5.5", "@bugsnag/react-native": "^7.11.0", - "@ecency/render-helper": "^2.2.8", + "@ecency/render-helper": "^2.2.9", "@esteemapp/dhive": "0.15.0", "@esteemapp/react-native-autocomplete-input": "^4.2.1", "@esteemapp/react-native-multi-slider": "^1.1.0", @@ -112,7 +112,7 @@ "react-native-reanimated": "^1", "react-native-receive-sharing-intent": "ecency/react-native-receive-sharing-intent", "react-native-render-html": "^6.0.5", - "react-native-restart": "0.0.17", + "react-native-restart": "^0.0.23", "react-native-safe-area-context": "^3.1.9", "react-native-screens": "^2.9.0", "react-native-scrollable-tab-view": "ecency/react-native-scrollable-tab-view", @@ -141,6 +141,7 @@ "redux-thunk": "^2.3.0", "rn-fetch-blob": "^0.12.0", "rn-placeholder": "^1.3.2", + "rtl-detect": "^1.0.4", "speakingurl": "^14.0.1", "stacktrace-parser": "0.1.4", "stream-browserify": "^1.0.0", diff --git a/src/components/basicHeader/view/basicHeaderStyles.js b/src/components/basicHeader/view/basicHeaderStyles.js index 04938f660..1d8740937 100644 --- a/src/components/basicHeader/view/basicHeaderStyles.js +++ b/src/components/basicHeader/view/basicHeaderStyles.js @@ -1,4 +1,5 @@ import EStyleSheet from 'react-native-extended-stylesheet'; +import { NativeModules } from 'react-native'; export default EStyleSheet.create({ container: { @@ -15,6 +16,11 @@ export default EStyleSheet.create({ backIcon: { fontSize: 24, color: '$iconColor', + transform: [{ scaleX: NativeModules.I18nManager.isRTL ? -1 : 1 }], + }, + gearIcon: { + fontSize: 24, + color: '$iconColor', }, saveIcon: { fontSize: 20, @@ -45,6 +51,7 @@ export default EStyleSheet.create({ }, iconButton: { marginRight: 24, + marginLeft: NativeModules.I18nManager.isRTL ? 24 : 0, justifyContent: 'center', alignSelf: 'center', }, @@ -65,11 +72,12 @@ export default EStyleSheet.create({ }, title: { color: '$iconColor', - alignSelf: 'center', + // alignSelf: 'center', fontSize: 16, marginLeft: 16, flexGrow: 1, fontWeight: '500', + textAlign: 'left', }, textInput: { color: '$iconColor', diff --git a/src/components/basicHeader/view/basicHeaderView.js b/src/components/basicHeader/view/basicHeaderView.js index a0482b012..a618653d3 100644 --- a/src/components/basicHeader/view/basicHeaderView.js +++ b/src/components/basicHeader/view/basicHeaderView.js @@ -175,7 +175,7 @@ const BasicHeaderView = ({ {isHasIcons && !isReply && ( ); - +const adjustDropdownFrame = (style:any) => { + style.left = 'auto' + style.right = 10 + return style +} const DropdownButtonView = ({ childIconWrapperStyle, children, @@ -90,6 +94,7 @@ const DropdownButtonView = ({ dropdownRowWrapper, ) } + adjustFrame={(style: any) => adjustDropdownFrame(style) } > {isHasChildIcon && !isLoading ? ( diff --git a/src/components/header/view/headerStyles.ts b/src/components/header/view/headerStyles.ts index 75359ead4..f8e55f880 100644 --- a/src/components/header/view/headerStyles.ts +++ b/src/components/header/view/headerStyles.ts @@ -1,5 +1,5 @@ import EStyleSheet from 'react-native-extended-stylesheet'; -import { Platform } from 'react-native'; +import { Platform, NativeModules } from 'react-native'; export default EStyleSheet.create({ container: { @@ -29,15 +29,17 @@ export default EStyleSheet.create({ avatarDefault: { borderTopRightRadius: 68 / 2, borderBottomRightRadius: 68 / 2, + overflow:'hidden' }, titleWrapper: { flexDirection: 'column', justifyContent: 'center', + alignItems: 'flex-start', marginHorizontal: 8, - flex:2 + flex:2, }, titleWrapperReverse: { - alignItems:'flex-end' + alignItems:'flex-end', }, title: { fontSize: 14, diff --git a/src/components/settingsItem/view/settingsItemStyles.js b/src/components/settingsItem/view/settingsItemStyles.js index 10684674a..4a39b95c8 100644 --- a/src/components/settingsItem/view/settingsItemStyles.js +++ b/src/components/settingsItem/view/settingsItemStyles.js @@ -12,6 +12,7 @@ export default EStyleSheet.create({ fontSize: 14, fontWeight: 'bold', flexGrow: 1, + textAlign: 'left', }, dropdownText: { fontSize: 14, diff --git a/src/components/sideMenu/view/sideMenuStyles.js b/src/components/sideMenu/view/sideMenuStyles.js index a9b832daf..fd7931f91 100644 --- a/src/components/sideMenu/view/sideMenuStyles.js +++ b/src/components/sideMenu/view/sideMenuStyles.js @@ -1,4 +1,5 @@ import EStyleSheet from 'react-native-extended-stylesheet'; +import { isRTL } from '../../../utils/I18nUtils'; import scalePx from '../../../utils/scalePx'; export default EStyleSheet.create({ @@ -18,14 +19,16 @@ export default EStyleSheet.create({ headerContentWrapper: { alignItems: 'center', height: 70, - flexDirection: 'row', + flexDirection: isRTL() ? 'row-reverse' : 'row', alignSelf: 'center', + flex: 1, }, contentView: { flex: 4, }, userAvatar: { - marginLeft: 32, + marginLeft: isRTL() ? 15 : 32, + marginRight: isRTL() ? 15 : 0, }, otherUserAvatar: { borderWidth: 0.1, @@ -63,10 +66,10 @@ export default EStyleSheet.create({ listItemText: { color: '$primaryDarkGray', marginLeft: 12, - alignSelf: 'center', fontWeight: '500', fontSize: 14, flex: 1, + textAlign: 'left', }, buttonText: { fontSize: 18, diff --git a/src/components/textInput/view/textInputView.js b/src/components/textInput/view/textInputView.js index 1c699e329..2242fb663 100644 --- a/src/components/textInput/view/textInputView.js +++ b/src/components/textInput/view/textInputView.js @@ -1,5 +1,5 @@ import React from 'react'; -import { TextInput } from 'react-native'; +import { TextInput, NativeModules } from 'react-native'; import { ThemeContainer } from '../../../containers'; @@ -12,6 +12,7 @@ const TextInputView = ({ innerRef, height, style, ...props }) => ( diff --git a/src/components/toggleSwitch/view/toggleSwitchView.js b/src/components/toggleSwitch/view/toggleSwitchView.js index 1c4158b62..b403ee359 100644 --- a/src/components/toggleSwitch/view/toggleSwitchView.js +++ b/src/components/toggleSwitch/view/toggleSwitchView.js @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { View, TouchableOpacity, Animated } from 'react-native'; +import { View, TouchableOpacity, Animated, NativeModules } from 'react-native'; // Constants @@ -85,7 +85,7 @@ class ToggleSwitchView extends PureComponent { _triggerAnimation = () => { const { width, translateX, isOn, duration } = this.state; - const toValue = isOn ? width - translateX : 0; + const toValue = isOn ? width - (NativeModules.I18nManager.isRTL ? 100 : translateX) : 0; //in rtl layout, set the translate value to 100 Animated.timing(this.offsetX, { toValue, diff --git a/src/components/upvote/view/upvoteStyles.js b/src/components/upvote/view/upvoteStyles.js index 58a258552..ddc5ad62f 100644 --- a/src/components/upvote/view/upvoteStyles.js +++ b/src/components/upvote/view/upvoteStyles.js @@ -86,10 +86,12 @@ export default EStyleSheet.create({ detailsText: { color: '$primaryDarkGray', fontSize: 12, + textAlign: 'right', }, popoverItemContent: { flexDirection: 'row', marginTop: 4, + justifyContent: 'space-between', }, popoverContent: { marginTop: 4, @@ -100,5 +102,6 @@ export default EStyleSheet.create({ color: '$primaryDarkGray', fontSize: 12, fontWeight: 'bold', + textAlign: 'left', }, }); diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index 1f64dc700..407996f12 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -433,7 +433,9 @@ "update_available_body":"Using latest version of Ecency gives you the best experience", "update": "Update Now", "remind_later": "Remind Later", - "failed_to_open": "Failed to open a link" + "failed_to_open": "Failed to open a link", + "restart_ecency": "Restart Ecency?", + "restart_ecency_desc": "Applying changes will require a restart." }, "post": { "reblog_alert": "Are you sure, you want to reblog?", diff --git a/src/screens/drafts/container/draftsContainer.js b/src/screens/drafts/container/draftsContainer.js index 297697ff4..a75587712 100644 --- a/src/screens/drafts/container/draftsContainer.js +++ b/src/screens/drafts/container/draftsContainer.js @@ -28,6 +28,8 @@ const DraftsContainer = ({ currentAccount, intl, navigation, dispatch }) => { const [schedules, setSchedules] = useState([]); const [isLoading, setIsLoading] = useState(false); + const [initialTabIndex] = useState(navigation.state?.params?.showSchedules ? 1 : 0); + useEffect(() => { _getDrafts(); _getSchedules(); @@ -145,6 +147,7 @@ const DraftsContainer = ({ currentAccount, intl, navigation, dispatch }) => { removeDraft={_removeDraft} moveScheduleToDraft={_moveScheduleToDraft} removeSchedule={_removeSchedule} + initialTabIndex={initialTabIndex} /> ); }; diff --git a/src/screens/drafts/screen/draftsScreen.js b/src/screens/drafts/screen/draftsScreen.js index 1b11284a9..0b4c7293e 100644 --- a/src/screens/drafts/screen/draftsScreen.js +++ b/src/screens/drafts/screen/draftsScreen.js @@ -15,7 +15,6 @@ import { BasicHeader, TabBar, DraftListItem, PostCardPlaceHolder } from '../../. import globalStyles from '../../../globalStyles'; import styles from './draftStyles'; import { OptionsModal } from '../../../components/atoms'; -import { jsonStringify } from '../../../utils/jsonUtils'; const DraftsScreen = ({ currentAccount, @@ -27,6 +26,7 @@ const DraftsScreen = ({ drafts, schedules, moveScheduleToDraft, + initialTabIndex, }) => { const [selectedId, setSelectedId] = useState(null); const ActionSheetRef = useRef(null); @@ -123,6 +123,7 @@ const DraftsScreen = ({ ( { @@ -1058,10 +1059,10 @@ class EditorContainer extends Component { ); setTimeout(() => { - navigation.navigate({ - routeName: ROUTES.SCREENS.DRAFTS, - key: currentAccount.name, - }); + navigation.replace(ROUTES.SCREENS.DRAFTS, + { + showSchedules:true + }) }, 3000); }) .catch((error) => { diff --git a/src/screens/settings/container/settingsContainer.js b/src/screens/settings/container/settingsContainer.js index b9a615c36..ce9dee774 100644 --- a/src/screens/settings/container/settingsContainer.js +++ b/src/screens/settings/container/settingsContainer.js @@ -6,7 +6,7 @@ import VersionNumber from 'react-native-version-number'; import Config from 'react-native-config'; import { injectIntl } from 'react-intl'; import messaging from '@react-native-firebase/messaging'; - +import { languageRestart } from '../../../utils/I18nUtils'; // Realm import { getExistUser, @@ -91,17 +91,17 @@ class SettingsContainer extends Component { } // Component Functions - _handleDropdownSelected = (action, actionType) => { - const { dispatch } = this.props; - + _handleDropdownSelected = async (action, actionType) => { + const { dispatch, selectedLanguage, intl } = this.props; switch (actionType) { case 'currency': this._currencyChange(action); break; case 'language': - dispatch(setLanguage(LANGUAGE_VALUE[action])); - setLanguage2DB(LANGUAGE_VALUE[action]); + await dispatch(setLanguage(LANGUAGE_VALUE[action])); + await setLanguage2DB(LANGUAGE_VALUE[action]); + await languageRestart(selectedLanguage, LANGUAGE_VALUE[action], intl); //restart the app and flip change layout according to lang direction break; case 'api': diff --git a/src/screens/settings/screen/settingsStyles.js b/src/screens/settings/screen/settingsStyles.js index 050d7d2f7..ec03ccc50 100644 --- a/src/screens/settings/screen/settingsStyles.js +++ b/src/screens/settings/screen/settingsStyles.js @@ -12,6 +12,7 @@ export default EStyleSheet.create({ }, cardTitle: { color: '$primaryBlue', + textAlign: 'left', }, paddingBottom: { paddingBottom: 20, diff --git a/src/utils/I18nUtils.ts b/src/utils/I18nUtils.ts new file mode 100644 index 000000000..2a6b5b8b9 --- /dev/null +++ b/src/utils/I18nUtils.ts @@ -0,0 +1,43 @@ +import { Alert, NativeModules } from 'react-native'; +import RNRestart from 'react-native-restart'; +import rtlDetect from 'rtl-detect'; + +export const isRTL = () => NativeModules.I18nManager.isRTL; + +export const languageRestart = (prevLang, lang, intl) => { + if (prevLang != lang) { + // if selected lang is RTL, switch the layout + if (rtlDetect.isRtlLang(lang)) { + NativeModules.I18nManager.forceRTL(true); + } else { + NativeModules.I18nManager.forceRTL(false); + } + + // if any prevLang or curr Lang is of different layout, alert user and restart + if (rtlDetect.isRtlLang(prevLang) !== rtlDetect.isRtlLang(lang)) { + Alert.alert( + intl.formatMessage({ + id: 'alert.restart_ecency', + }), + intl.formatMessage({ + id: 'alert.restart_ecency_desc', + }), + [ + { + text: intl.formatMessage({ + id: 'alert.cancel', + }), + onPress: () => console.log('Cancel Pressed'), + style: 'cancel', + }, + { + text: intl.formatMessage({ + id: 'alert.confirm', + }), + onPress: () => RNRestart.Restart(), + }, + ], + ); + } + } +}; diff --git a/yarn.lock b/yarn.lock index 7bc94163a..2bc08e01f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1031,10 +1031,10 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@ecency/render-helper@^2.2.8": - version "2.2.8" - resolved "https://registry.yarnpkg.com/@ecency/render-helper/-/render-helper-2.2.8.tgz#1c6e8b2e467f64097bf692a26f2a3103bc1e32f7" - integrity sha512-RPsM6Pbhb3Yfh2h1XiHj17fPM0doZTut3Wppf8iVGzwqdiaZ1NYI+mmYn5lG2lK8WcBAez0vHZeoHqBxdNGMWg== +"@ecency/render-helper@^2.2.9": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@ecency/render-helper/-/render-helper-2.2.9.tgz#067a4f3d3c27bcb814648c692a4dfb868035436b" + integrity sha512-Oiz2N7qbwRAuS7dtbSRmCr7Yp2wUyEmBNtEun1byYoE+1g4k7dxJLsigs9ErrJzZ/yFQVcLEB1YrfjZczl/vfQ== dependencies: he "^1.2.0" lolight "^1.4.0" @@ -8691,10 +8691,10 @@ react-native-render-html@^6.0.5: stringify-entities "^3.1.0" urijs "^1.19.6" -react-native-restart@0.0.17: - version "0.0.17" - resolved "https://registry.yarnpkg.com/react-native-restart/-/react-native-restart-0.0.17.tgz#c1f38e019d1a2114248d496698e7951e9435ba91" - integrity sha512-UwFPDssMFoyDbF2aLARIHWt5g/o0TtxCXK9WIY+0iNpkgG9qWd+n80XBwXioNCdgy39ZQ5yfJBJRwtMLDgABag== +react-native-restart@^0.0.23: + version "0.0.23" + resolved "https://registry.yarnpkg.com/react-native-restart/-/react-native-restart-0.0.23.tgz#9b53062ebc692f469d0662c06879cb4d34c62520" + integrity sha512-BTs3YNl0MFyTgYgq6oQOspVV7+8Umm2QeuHWJ8xfRsjdHIUBoKF/Bxe1IMGAO5vHPcNwN+lHE6Mf58Tu4HS9/w== react-native-safe-area-context@^3.1.9: version "3.1.9" @@ -9390,6 +9390,11 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +rtl-detect@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" + integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== + run-async@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"