diff --git a/frontend/src/MancalaApp.tsx b/frontend/src/MancalaApp.tsx index 27e2a36..9c69c48 100644 --- a/frontend/src/MancalaApp.tsx +++ b/frontend/src/MancalaApp.tsx @@ -14,6 +14,7 @@ import { RTMTWS } from './rtmt/rtmt_websocket'; import { getColorByBrightness } from './util/ColorUtil'; import { Theme } from './theme/Theme'; import LobyPage from './routes/LobyPage'; +import PrivacyPage from './routes/PrivacyPage'; import swal from 'sweetalert'; import { ConnectionState } from './rtmt/rtmt'; import Util from './util/Util'; @@ -80,6 +81,8 @@ const MancalaApp: FunctionComponent = () => { }> + }> + diff --git a/frontend/src/routes/PrivacyPage.tsx b/frontend/src/routes/PrivacyPage.tsx new file mode 100644 index 0000000..417d226 --- /dev/null +++ b/frontend/src/routes/PrivacyPage.tsx @@ -0,0 +1,87 @@ +import * as React from 'react'; +import { FunctionComponent, useEffect } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; +import HeaderBar from '../components/headerbar/HeaderBar'; +import HeaderbarIcon from '../components/headerbar/HeaderbarIcon'; +import HeaderbarTitle from '../components/headerbar/HeaderbarTitle'; +import ThemeSwitchMenu from '../components/headerbar/ThemeSwitchMenu'; +import PageContainer from '../components/PageContainer'; +import Row from '../components/Row'; +import { Context } from '../context/context'; +import { Theme } from '../theme/Theme'; +import { getColorByBrightness } from '../util/ColorUtil'; + +const PrivacyPage: FunctionComponent<{ + context: Context, + userKey?: string, + theme: Theme +}> = ({ context, userKey, theme }) => { + + const textColorOnAppBar = getColorByBrightness( + context.themeManager.theme.appBarBgColor, + context.themeManager.theme.textColor, + context.themeManager.theme.textLightColor + ); + const textColorOnBoard = getColorByBrightness( + context.themeManager.theme.background, + "#000", + "#aaa" + ); + return ( + + + + + + + + + + + + + + +
+ +

Privacy Policy

+

The Mancala team and volunteers built the Mancala app as a open source app. This SERVICE is provided by mancala team and volunteers at no cost and is intended + for use as is.

+

This page is used to inform website visitors regarding our policies with the collection, use, and + disclosure of Personal Information if anyone decided to use our Service.

+ +

The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, + which is accessible at Mancala, unless otherwise defined in this Privacy Policy.

+ +

Information Collection and Use

+

The application does not collect any user information and data. The application uses a unique key received from the remote server and stored on the client to identify the anonymous user.

+ +

Cookies

+

Cookies are files with small amount of data that is commonly used an anonymous unique identifier. + These are sent to your browser from the website that you visit and are stored on your devices’s + internal memory.

+ +

Security

+

We value your trust in providing us your Personal Information, thus we are striving to use + commercially acceptable means of protecting it. But remember that no method of transmission over + the internet, or method of electronic storage is 100% secure and reliable, and we cannot + guarantee its absolute security.

+ +

Changes to This Privacy Policy

+

We may update our Privacy Policy from time to time. Thus, you are advised to review this page + periodically for any changes. We will notify you of any changes by posting the new Privacy Policy + on this page. These changes are effective immediately, after they are posted on this page.

+ +

Contact Us

+

If you have any questions or suggestions about our Privacy Policy, do not hesitate to contact + us.

+
+
+ ); +} + +export default PrivacyPage; \ No newline at end of file diff --git a/mobile/package.json b/mobile/package.json index 6220386..98f65e8 100644 --- a/mobile/package.json +++ b/mobile/package.json @@ -23,6 +23,7 @@ "react-native-safe-area-context": "^4.9.0", "react-native-screens": "^3.29.0", "react-native-snackbar": "^2.6.2", + "react-native-svg": "^15.1.0", "tiny-emitter": "^2.1.0", "uuid": "^9.0.1" }, diff --git a/mobile/src/App.tsx b/mobile/src/App.tsx index 35f2003..85c9f77 100644 --- a/mobile/src/App.tsx +++ b/mobile/src/App.tsx @@ -15,6 +15,8 @@ import { NativeModules, I18nManager, Platform } from 'react-native' // https://github.com/uuidjs/uuid/issues/514#issuecomment-691475020 import 'react-native-get-random-values'; +import HelpScreen from './screens/HelpScreen'; +import { getColorByBrightness } from './util/ColorUtil'; const Stack = createNativeStackNavigator(); @@ -96,15 +98,26 @@ function App() { // context.themeManager.theme.textColor, // context.themeManager.theme.textLightColor //); + const textColorOnAppBar = getColorByBrightness( + context.themeManager.theme.appBarBgColor, + context.themeManager.theme.textColor, + context.themeManager.theme.textLightColor + ); + + const headerStyle = { backgroundColor: context.themeManager.theme.appBarBgColor }; + const headerTintColor = textColorOnAppBar; + return ( + options={{ title: t("Mancala"), headerStyle, headerTintColor }} /> + options={{ title: t("Mancala"), headerStyle, headerTintColor }} /> + options={{ title: t("Mancala"), headerStyle, headerTintColor }} /> + ); diff --git a/mobile/src/const/config.ts b/mobile/src/const/config.ts index 590b1fa..5f37943 100644 --- a/mobile/src/const/config.ts +++ b/mobile/src/const/config.ts @@ -14,4 +14,8 @@ export const server: Server = useLocalServer ? { wsServerAdress: "wss://mancala.segin.one", }; -export const RTMT_WS_PING_INTERVAL = 1000, RTMT_WS_PING_INTERVAL_BUFFER_TIME = 2000; \ No newline at end of file +export const RTMT_WS_PING_INTERVAL = 1000, RTMT_WS_PING_INTERVAL_BUFFER_TIME = 2000; + +export const WEB_APP_URL = "https://playmancala.app"; + +export const PRIVAcY_URL = "https://playmancala.app/privacy"; \ No newline at end of file diff --git a/mobile/src/localization/en.ts b/mobile/src/localization/en.ts index f7c753b..6200121 100644 --- a/mobile/src/localization/en.ts +++ b/mobile/src/localization/en.ts @@ -35,5 +35,8 @@ export default { AreYouSureToLeaveGame: "Are you sure to leave game?", Yes: "Yes", Cancel: "Cancel", + Help: "Help", + WebApp: "Goto WebApp", + Privacy: "Open Privacy Policy " } }; \ No newline at end of file diff --git a/mobile/src/localization/tr.ts b/mobile/src/localization/tr.ts index 256c8ae..8aea9da 100644 --- a/mobile/src/localization/tr.ts +++ b/mobile/src/localization/tr.ts @@ -34,6 +34,9 @@ export default { UCanNotPlayEmptyPit: "Boş kuyu ile oynayamazsın", AreYouSureToLeaveGame: "Oyundan ayrılmak istediğine emin misin?", Yes: "Evet", - Cancel: "İptal" + Cancel: "İptal", + Help: "Yardım", + WebApp: "Web Uygulamasına Git", + Privacy: "Gizlilik Politikasını Göster" } }; \ No newline at end of file diff --git a/mobile/src/screens/GameScreen.tsx b/mobile/src/screens/GameScreen.tsx index b7acc0b..5c1f79d 100644 --- a/mobile/src/screens/GameScreen.tsx +++ b/mobile/src/screens/GameScreen.tsx @@ -22,6 +22,8 @@ import UserStatus from '../components/UserStatus'; import BoardToolbar from '../components/board/BoardToolbar'; import BoardView from '../components/board/BoardView'; import CircularPanel from '../components/CircularPanel'; +import { SvgXml } from 'react-native-svg'; +import helpSvg from '../svg/help'; export function GameScreen({ navigation, route }: GameScreenProps) { const { context, gameId, userKey } = route.params; @@ -215,15 +217,28 @@ export function GameScreen({ navigation, route }: GameScreenProps) { const isGameEnded = game?.mancalaGame.state === "ended" || leftPlayer; navigation.setOptions({ headerRight: () => ( - { - if (isGameEnded) { - onNewGameClick(); - } else { - onLeaveGameClick(); - } + - {isGameEnded ? t('NewGame') : t('Leave')}} /> - + { + if (isGameEnded) { + onNewGameClick(); + } else { + onLeaveGameClick(); + } + }}> + {isGameEnded ? t('NewGame') : t('Leave')}} /> + + { + navigation.push("Help", { context }) + }}> + + + + ), }); } diff --git a/mobile/src/screens/HelpScreen.tsx b/mobile/src/screens/HelpScreen.tsx new file mode 100644 index 0000000..efd6997 --- /dev/null +++ b/mobile/src/screens/HelpScreen.tsx @@ -0,0 +1,42 @@ +import * as React from 'react'; +import { View, Text, Button, Pressable, Linking } from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { HelpScreenProps } from '../types'; +import Snackbar from 'react-native-snackbar'; +import { PRIVAcY_URL, WEB_APP_URL } from '../const/config'; + +export default function HelpScreen({ navigation, route }: HelpScreenProps) { + + const { context } = route.params; + const { t } = useTranslation(); + + const onGotoWebAppClick = () => { + Linking.openURL(WEB_APP_URL).catch(()=>{ + Snackbar.show({text: t("InternalErrorOccurred")}); + }) + } + + const onGotoPrivacyClick = () => { + Linking.openURL(PRIVAcY_URL).catch(()=>{ + Snackbar.show({text: t("InternalErrorOccurred")}); + }) + } + + return ( + + + {t('WebApp')} + + + {t('Privacy')} + + + ); +} \ No newline at end of file diff --git a/mobile/src/screens/HomeScreen.tsx b/mobile/src/screens/HomeScreen.tsx index 8df57e4..47dbcd7 100644 --- a/mobile/src/screens/HomeScreen.tsx +++ b/mobile/src/screens/HomeScreen.tsx @@ -3,16 +3,41 @@ import { View, Button, Pressable, Text } from 'react-native'; import { useTranslation } from 'react-i18next'; import { HomeScreenProps } from '../types'; import CircularPanel from '../components/CircularPanel'; +import { SvgXml } from 'react-native-svg'; +import helpSvg from '../svg/help'; +import { getColorByBrightness } from '../util/ColorUtil'; export function HomeScreen({ navigation, route }: HomeScreenProps) { const { context } = route.params; const { t } = useTranslation(); + const textColorOnAppBar = getColorByBrightness( + context.themeManager.theme.appBarBgColor, + context.themeManager.theme.textColor, + context.themeManager.theme.textLightColor + ); + + const updateHeaderButton = () => { + navigation.setOptions({ + headerRight: () => ( + { + navigation.push("Help", { context }) + }}> + + + ), + }); + } + + React.useEffect(() => { + updateHeaderButton(); + }, []); + return ( navigation.replace('Loby', { context })}> - {t('NewGame')}}/> + {t('NewGame')}} /> ); diff --git a/mobile/src/screens/LobyScreen.tsx b/mobile/src/screens/LobyScreen.tsx index 844f073..3822763 100644 --- a/mobile/src/screens/LobyScreen.tsx +++ b/mobile/src/screens/LobyScreen.tsx @@ -6,6 +6,9 @@ import { useEffect } from 'react'; import { CommonMancalaGame } from 'mancala.js'; import { channel_cancel_new_game, channel_on_game_start } from '../const/channel_names'; import CircularPanel from '../components/CircularPanel'; +import { getColorByBrightness } from '../util/ColorUtil'; +import { SvgXml } from 'react-native-svg'; +import helpSvg from '../svg/help'; export default function LobyScreen({ navigation, route }: LobyScreenProps) { @@ -34,6 +37,28 @@ export default function LobyScreen({ navigation, route }: LobyScreenProps) { } }, []); + const textColorOnAppBar = getColorByBrightness( + context.themeManager.theme.appBarBgColor, + context.themeManager.theme.textColor, + context.themeManager.theme.textLightColor + ); + + const updateHeaderButton = () => { + navigation.setOptions({ + headerRight: () => ( + { + navigation.push("Help", { context }) + }}> + + + ), + }); + } + + React.useEffect(() => { + updateHeaderButton(); + }, []); + return ( {t('SearchingOpponent') + " " + t('PleaseWait') + "..."}} /> diff --git a/mobile/src/svg/help.tsx b/mobile/src/svg/help.tsx new file mode 100644 index 0000000..1be024a --- /dev/null +++ b/mobile/src/svg/help.tsx @@ -0,0 +1,12 @@ +import Svg, { G, Path } from "react-native-svg"; + +const helpSvg = + ` + + + + + +`; + +export default helpSvg; \ No newline at end of file diff --git a/mobile/src/svg/lightMode.tsx b/mobile/src/svg/lightMode.tsx new file mode 100644 index 0000000..6d320cf --- /dev/null +++ b/mobile/src/svg/lightMode.tsx @@ -0,0 +1,8 @@ +const lightModeSvg = +` + + + +`; + +export default lightModeSvg; \ No newline at end of file diff --git a/mobile/src/svg/settings.tsx b/mobile/src/svg/settings.tsx new file mode 100644 index 0000000..930871b --- /dev/null +++ b/mobile/src/svg/settings.tsx @@ -0,0 +1,20 @@ +const settingsSvg = +` + + + + + +`; + +export default settingsSvg; \ No newline at end of file diff --git a/mobile/src/types/index.ts b/mobile/src/types/index.ts index 931ffb7..4b2db02 100644 --- a/mobile/src/types/index.ts +++ b/mobile/src/types/index.ts @@ -5,6 +5,7 @@ export type RootStackParamList = { Home: { context: Context }, Loby: { context: Context }, Game: { context: Context, gameId: string, userKey: string } + Help: { context: Context } }; export type HomeScreenProps = NativeStackScreenProps; @@ -12,3 +13,5 @@ export type HomeScreenProps = NativeStackScreenProps export type LobyScreenProps = NativeStackScreenProps; export type GameScreenProps = NativeStackScreenProps; + +export type HelpScreenProps = NativeStackScreenProps; \ No newline at end of file diff --git a/mobile/yarn.lock b/mobile/yarn.lock index 4f23214..a4b4a2a 100644 --- a/mobile/yarn.lock +++ b/mobile/yarn.lock @@ -2500,6 +2500,11 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2846,6 +2851,30 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" @@ -3002,6 +3031,36 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3027,6 +3086,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +entities@^4.2.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + envinfo@^7.10.0: version "7.11.1" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.1.tgz#2ffef77591057081b0129a8fd8cf6118da1b94e1" @@ -4881,6 +4945,11 @@ marky@^1.2.2: resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + memoize-one@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -5230,6 +5299,13 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + nullthrows@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" @@ -5684,6 +5760,14 @@ react-native-snackbar@^2.6.2: resolved "https://registry.yarnpkg.com/react-native-snackbar/-/react-native-snackbar-2.6.2.tgz#7c0d0d93bfb5822fb1f41f00d29383f522c02185" integrity sha512-edAubZJiBowwQUXJV5oXbMqitQ9vw7JzWUCczeTPVo6lRa+FzsUjiCQBHdWBbCw/N8/Q7jgKg4juNXU/bXZdXg== +react-native-svg@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-15.1.0.tgz#07c75f29b1d641faba50144c7ccd21604b368420" + integrity sha512-p0Sx0EpQNk1nu6UcMEiB8K9P04n3J7s+pNYUwf1d/Yz+v4hk961VjuVqjyndgiEbHZyWiKWLZRVNuvLpwjPY2A== + dependencies: + css-select "^5.1.0" + css-tree "^1.1.3" + react-native@0.73.6: version "0.73.6" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.6.tgz#ed4c675e205a34bd62c4ce8b9bd1ca5c85126d5b"