Skip to content

Commit

Permalink
Merge pull request #113 from eurofurence/feature/theme-picker
Browse files Browse the repository at this point in the history
Feature/theme picker
  • Loading branch information
Requinard authored Aug 21, 2022
2 parents e957354 + a33ec53 commit 4ef40e3
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 102 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
web-build

.vscode/
package-lock.json

Expand Down
83 changes: 0 additions & 83 deletions app.config.js

This file was deleted.

103 changes: 103 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"expo": {
"runtimeVersion": {
"policy": "appVersion"
},
"entryPoint": "./src/index.tsx",
"name": "Eurofurence",
"slug": "ef-app-react-native",
"description": "Your one stop shop to the convention!",
"owner": "eurofurence",
"version": "3.0.0",
"orientation": "default",
"icon": "./assets/images/playstore.png",
"userInterfaceStyle": "automatic",
"scheme": "eurofurence",
"splash": {
"image": "./assets/images/playstore.png",
"resizeMode": "contain",
"backgroundColor": "#035451"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"assets/**/*",
"android/**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"package": "org.eurofurence.connavigator",
"googleServicesFile": "./assets/android/google-services.json",
"splash": {
"resizeMode": "native"
},
"adaptiveIcon": {
"foregroundImage": "./assets/images/playstore.png",
"backgroundColor": "#006459"
},
"intentFilters": [
{
"action": "VIEW",
"autoVerify": false,
"data": [
{
"scheme": "https",
"host": "app.eurofurence.org",
"pathPrefix": "/EF26/Web/"
}
],
"category": [
"BROWSABLE",
"DEFAULT"
]
}
],
"permissions": [
"INTERNET",
"VIBRATE",
"WRITE_EXTERNAL_STORAGE"
]
},
"web": {
"favicon": "./assets/images/playstore.png",
"config": {
"firebase": {
"apiKey": "AIzaSyCF365l8zUac096MFPLUtbPE6sqH182G2Q",
"authDomain": "eurofurence-de86f.firebaseapp.com",
"databaseURL": "https://eurofurence-de86f.firebaseio.com",
"projectId": "eurofurence-de86f",
"storageBucket": "eurofurence-de86f.appspot.com",
"messagingSenderId": "1003745003618",
"appId": "1:1003745003618:web:6eca6a1ec8f5d5bfe9e93b",
"measurementId": "G-83EP75M02N"
}
}
},
"plugins": [
"sentry-expo",
[
"expo-notifications",
{
"icon": "./assets/images/notification.png",
"color": "#006459"
}
]
],
"hooks": {
"postPublish": [
{
"file": "sentry-expo/upload-sourcemaps",
"config": {
"organization": "eurofurence",
"project": "ef-app_react-native",
"authToken": false,
"setCommits": true
}
}
]
}
}
}
Binary file added assets/audio/cheese.webm
Binary file not shown.
Binary file added assets/audio/sheesh.webm
Binary file not shown.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "ef-app_react-native",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"homepage": "http://eurofurence.github.io/ef-app_react-native/",
"contributors": [
{
"name": "requinard"
Expand Down Expand Up @@ -33,7 +34,9 @@
"test": "jest",
"eas-build-post-install": "tsc --noEmit && yarn lint:translations && yarn lint:code",
"bundle:android": "eas build --platform android --profile production",
"bundle:web": "expo export:web",
"submit:android": "eas submit --platform android",
"submit:web": "gh-pages -d web-build",
"local:android": "yarn tsc --noEmit && yarn lint && npx eas build --platform android --profile preview --local",
"local:android:preview": "yarn tsc --noEmit && yarn lint && npx eas build --platform android --profile preview --local",
"local:android:production": "yarn tsc --noEmit && yarn lint && npx eas build --platform android --profile production --local",
Expand All @@ -55,6 +58,7 @@
"@sentry/react-native": "^4.1.3",
"expo": "^46.0.0",
"expo-application": "~4.2.2",
"expo-av": "~12.0.4",
"expo-checkbox": "~2.2.0",
"expo-constants": "~13.2.3",
"expo-device": "~4.3.0",
Expand Down Expand Up @@ -114,6 +118,7 @@
"eslint-config-universe": "^11.0.0",
"eslint-plugin-i18n-json": "^3.1.0",
"eslint-plugin-testing-library": "^5.5.1",
"gh-pages": "^4.0.0",
"jest": "^26.6.3",
"jest-expo": "^46.0.0",
"prettier": "^2.7.1",
Expand Down
31 changes: 21 additions & 10 deletions src/app/About.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { nativeApplicationVersion, nativeBuildVersion } from "expo-application";
import { FC } from "react";
import { Sound } from "expo-av/build/Audio/Sound";
import { FC, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Image, Linking, ScrollView } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
Expand All @@ -13,7 +14,8 @@ import { Col } from "../components/Containers/Col";
import { Floater } from "../components/Containers/Floater";
import { Header } from "../components/Containers/Header";
import { Row } from "../components/Containers/Row";
import { useAppSelector } from "../store";
import { useAppDispatch, useAppSelector } from "../store";
import { setTheme } from "../store/settings.slice";
import { appStyles } from "./AppStyles";

const extraThanksMarkdown = `
Expand Down Expand Up @@ -80,8 +82,8 @@ And Sentry helps us out with exception tracing.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.`;

export const Credit: FC<{ uri: string; name: string; role: string; onPress?: () => void }> = ({ uri, name, role, onPress }) => (
<TouchableOpacity disabled={onPress === undefined} onPress={onPress}>
export const Credit: FC<{ uri: string; name: string; role: string; onEasterEgg?: () => void }> = ({ uri, name, role, onEasterEgg }) => (
<TouchableOpacity disabled={onEasterEgg === undefined} onLongPress={onEasterEgg} delayLongPress={2000}>
<Row type={"center"} style={{ marginVertical: 5 }}>
<Image
source={{ uri, height: 60, width: 60 }}
Expand All @@ -92,10 +94,7 @@ export const Credit: FC<{ uri: string; name: string; role: string; onPress?: ()

<Col style={{ flex: 1, marginLeft: 10 }}>
<Label type={"h2"}>{name}</Label>
<Label>
{role}
{}
</Label>
<Label>{role}</Label>
</Col>
</Row>
</TouchableOpacity>
Expand All @@ -105,6 +104,18 @@ export const AboutScreen = () => {
const { t } = useTranslation("About");
const safe = useSafeAreaInsets();
const showHelpButtons = useAppSelector((state) => state.settingsSlice.showDevMenu ?? false);
const dispatch = useAppDispatch();

const requinardEgg = useCallback(async () => {
const { sound } = await Sound.createAsync(require("../../assets/audio/cheese.webm"));
await sound.playAsync();
dispatch(setTheme("requinard"));
}, [dispatch]);

const pazuzuEgg = useCallback(async () => {
const { sound } = await Sound.createAsync(require("../../assets/audio/sheesh.webm"));
await sound.playAsync();
}, []);
return (
<ScrollView style={[appStyles.abs, safe]} stickyHeaderIndices={[0]} stickyHeaderHiddenOnScroll>
<Header>{t("header")}</Header>
Expand All @@ -124,8 +135,8 @@ export const AboutScreen = () => {

<Section title={t("developed_by")} icon={"code-json"} />
<Credit uri={"https://avatars.githubusercontent.com/u/13329381"} name={"Luchs"} role={"Project management and getting us to move our butts in gear"} />
<Credit uri={"https://avatars.githubusercontent.com/u/5929561"} name={"Pazuzu"} role={"React Development and UI design"} />
<Credit uri={"https://avatars.githubusercontent.com/u/5537850"} name={"Requinard"} role={"React Development and app mechanics"} />
<Credit uri={"https://avatars.githubusercontent.com/u/5929561"} name={"Pazuzu"} role={"React Development and UI design"} onEasterEgg={pazuzuEgg} />
<Credit uri={"https://avatars.githubusercontent.com/u/5537850"} name={"Requinard"} role={"React Development and app mechanics"} onEasterEgg={requinardEgg} />
<Credit uri={"https://avatars.githubusercontent.com/u/12624320"} name={"Shez"} role={"iOS Development"} />
<Credit uri={"https://avatars.githubusercontent.com/u/3359222"} name={"Fenrikur"} role={"iOS Development"} />
<MarkdownContent>{extraThanksMarkdown}</MarkdownContent>
Expand Down
60 changes: 60 additions & 0 deletions src/app/Settings/ThemePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import _ from "lodash";
import React from "react";
import { useTranslation } from "react-i18next";
import { StyleSheet } from "react-native";

import { Label } from "../../components/Atoms/Label";
import { Button } from "../../components/Containers/Button";
import { Col } from "../../components/Containers/Col";
import { Row } from "../../components/Containers/Row";
import { useAppDispatch, useAppSelector } from "../../store";
import { setTheme } from "../../store/settings.slice";

const useableThemes = [undefined, "light", "dark"];
export const ThemePicker = () => {
const { t } = useTranslation("Settings", { keyPrefix: "theme" });
const dispatch = useAppDispatch();
const theme = useAppSelector((state) => state.settingsSlice.theme);

return (
<Col type={"stretch"}>
<Label variant={"bold"}>{t("title")}</Label>
<Label variant={"narrow"}>{t("description")}</Label>

<Row type={"center"} variant={"center"} style={styles.selector}>
<Button style={[styles.button, styles.left]} outline={theme === undefined} onPress={() => dispatch(setTheme(undefined))}>
{t("system")}
</Button>
{!useableThemes.includes(theme) && (
<Button style={styles.button} outline onPress={() => setTheme(theme)}>
{_.capitalize(theme)}
</Button>
)}
<Button style={styles.button} outline={theme === "light"} onPress={() => dispatch(setTheme("light"))}>
{t("light")}
</Button>
<Button style={[styles.button, styles.right]} outline={theme === "dark"} onPress={() => dispatch(setTheme("dark"))}>
{t("dark")}
</Button>
</Row>
</Col>
);
};

const styles = StyleSheet.create({
selector: {
marginTop: 16,
},
button: {
flexGrow: 1,
borderRadius: 0,
},
left: {
borderBottomLeftRadius: 16,
borderTopLeftRadius: 16,
},
right: {
borderTopRightRadius: 16,
borderBottomRightRadius: 16,
},
});
4 changes: 4 additions & 0 deletions src/app/Settings/UserSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useAppDispatch, useAppSelector } from "../../store";
import { logout } from "../../store/authorization.slice";
import { setAnalytics, toggleDevMenu } from "../../store/settings.slice";
import { LoginForm } from "../MainMenu/PagerLogin";
import { ThemePicker } from "./ThemePicker";

type Language = {
code: Translations;
Expand Down Expand Up @@ -71,6 +72,9 @@ export const UserSettings = () => {
return (
<View>
<Section title={t("settingsSection")} icon={"cog"} />
<SettingItem>
<ThemePicker />
</SettingItem>
<SettingItem>
<TouchableOpacity
style={{ flexDirection: "row", alignItems: "center" }}
Expand Down
2 changes: 1 addition & 1 deletion src/context/NavigationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const linkingFrom = (days: RecordId[], tracks: RecordId[], rooms: RecordId[]): L
// TODO: Use configuration constants here.
// Return the composed linking object.
return {
prefixes: [Linking.createURL(`/`), Linking.createURL(`/${conId}/Web/`), `https://app.eurofurence.org`],
prefixes: [Linking.createURL(`/`), Linking.createURL(`/${conId}/Web/`), `https://app.eurofurence.org`, "http://eurofurence.github.io/ef-app_react-native"],
config: {
initialRouteName: "Areas",
screens: {
Expand Down
Loading

0 comments on commit 4ef40e3

Please sign in to comment.