diff --git a/.github/workflows/deploy-static-main.yml b/.github/workflows/deploy-static-main.yml index 89b62d1..2a78936 100644 --- a/.github/workflows/deploy-static-main.yml +++ b/.github/workflows/deploy-static-main.yml @@ -67,7 +67,7 @@ jobs: run: cd OwnTube.tv/ && npm run test build_android_apk: - needs: code_quality + needs: [code_quality, build_info] runs-on: ubuntu-latest steps: - name: Checkout @@ -119,7 +119,7 @@ jobs: path: "./OwnTube.tv/android/app/build/outputs/apk/release/app-release.apk" deploy_web: - needs: code_quality + needs: [code_quality, build_info] runs-on: ubuntu-latest environment: name: github-pages diff --git a/OwnTube.tv/.prettierignore b/OwnTube.tv/.prettierignore index 0a71e70..425a53c 100644 --- a/OwnTube.tv/.prettierignore +++ b/OwnTube.tv/.prettierignore @@ -2,3 +2,4 @@ **/dist/* package.json app.json +assets/selection.json diff --git a/OwnTube.tv/App.tsx b/OwnTube.tv/App.tsx index 12b086c..c520b8f 100644 --- a/OwnTube.tv/App.tsx +++ b/OwnTube.tv/App.tsx @@ -1,10 +1,8 @@ -import { StatusBar } from "expo-status-bar"; import RootLayout from "./app/_layout"; export default function App() { return ( <> - ); diff --git a/OwnTube.tv/app.json b/OwnTube.tv/app.json index fb3ffaf..3e38ae0 100644 --- a/OwnTube.tv/app.json +++ b/OwnTube.tv/app.json @@ -40,7 +40,13 @@ "fonts": ["assets/fonts/icomoon.ttf"] } ], - "expo-localization" + "expo-localization", + [ + "expo-screen-orientation", + { + "initialOrientation": "DEFAULT" + } + ] ] } } diff --git a/OwnTube.tv/app/_layout.tsx b/OwnTube.tv/app/_layout.tsx index cd051a7..2fd7cdc 100644 --- a/OwnTube.tv/app/_layout.tsx +++ b/OwnTube.tv/app/_layout.tsx @@ -1,7 +1,7 @@ import { Link, Stack, useLocalSearchParams } from "expo-router"; import { Platform, StyleSheet } from "react-native"; import { ROUTES, STORAGE } from "../types"; -import { DarkTheme, DefaultTheme, ThemeProvider } from "@react-navigation/native"; +import { ThemeProvider } from "@react-navigation/native"; import { AppConfigContextProvider, ColorSchemeContextProvider, useColorSchemeContext } from "../contexts"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; @@ -24,12 +24,14 @@ import { Inter_900Black, } from "@expo-google-fonts/inter"; import { IcoMoonIcon } from "../components"; +import { colorSchemes } from "../theme"; import { GestureHandlerRootView } from "react-native-gesture-handler"; +import { StatusBar } from "expo-status-bar"; const RootStack = () => { const { backend } = useLocalSearchParams(); const { scheme } = useColorSchemeContext(); - const theme = scheme === "dark" ? DarkTheme : DefaultTheme; + const theme = scheme === "dark" ? colorSchemes.dark : colorSchemes.light; const { t, i18n } = useTranslation(); useEffect(() => { @@ -37,37 +39,40 @@ const RootStack = () => { }, []); return ( - - {children}, - }} - > - <>, - headerRight: () => <>, + <> + + + {children}, }} - /> - ( - - - - ), - }} - name={`(home)/${ROUTES.SETTINGS}`} - /> - - - }} /> - + > + <>, + headerRight: () => <>, + }} + /> + ( + + + + ), + }} + name={`(home)/${ROUTES.SETTINGS}`} + /> + + + }} /> + + ); }; diff --git a/OwnTube.tv/assets/fonts/icomoon.ttf b/OwnTube.tv/assets/fonts/icomoon.ttf index c6b9f26..583afbd 100644 Binary files a/OwnTube.tv/assets/fonts/icomoon.ttf and b/OwnTube.tv/assets/fonts/icomoon.ttf differ diff --git a/OwnTube.tv/assets/selection.json b/OwnTube.tv/assets/selection.json index 152c286..715400d 100644 --- a/OwnTube.tv/assets/selection.json +++ b/OwnTube.tv/assets/selection.json @@ -1,365 +1 @@ -{ - "IcoMoonType": "selection", - "icons": [ - { - "icon": { - "paths": [ - "M853.329 469.333v85.333h-512l234.666 234.667-60.587 60.587-337.92-337.92 337.92-337.922 60.587 60.587-234.666 234.668h512z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Arrow Left"] - }, - "attrs": [{}], - "properties": { "order": 2, "id": 19, "name": "Arrow-Left", "prevSize": 32, "code": 59648 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 0 - }, - { - "icon": { - "paths": ["M316.16 366.081l195.84 195.839 195.84-195.839 60.16 60.586-256 256-256-256 60.16-60.586z"], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Chevron"] - }, - "attrs": [{}], - "properties": { "order": 3, "id": 18, "name": "Chevron", "prevSize": 32, "code": 59649 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 1 - }, - { - "icon": { - "paths": [ - "M273.067 810.667l-59.733-59.733 238.933-238.933-238.933-238.933 59.733-59.733 238.933 238.933 238.933-238.933 59.733 59.733-238.933 238.933 238.933 238.933-59.733 59.733-238.933-238.933-238.933 238.933z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Close"] - }, - "attrs": [{}], - "properties": { "order": 4, "id": 17, "name": "Close", "prevSize": 32, "code": 59650 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 2 - }, - { - "icon": { - "paths": [ - "M298.667 768v-682.667h554.667v682.667h-554.667zM384 682.667h384v-512h-384v512zM128 938.667v-682.667h85.333v597.333h469.333v85.333h-554.667z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Content Copy"] - }, - "attrs": [{}], - "properties": { "order": 5, "id": 16, "name": "Content-Copy", "prevSize": 32, "code": 59651 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 3 - }, - { - "icon": { - "paths": [ - "M512 896c-106.667 0-197.333-37.333-272-112s-112-165.333-112-272c0-106.667 37.333-197.333 112-272s165.333-112 272-112c9.954 0 19.742 0.355 29.355 1.067s19.029 1.778 28.245 3.2c-29.154 20.622-52.45 47.474-69.888 80.555s-26.142 68.807-26.112 107.179c0 64 22.4 118.4 67.2 163.2s99.2 67.2 163.2 67.2c39.113 0 75.021-8.717 107.733-26.155s59.379-40.717 80-69.845c1.421 9.246 2.487 18.658 3.2 28.245s1.067 19.371 1.067 29.355c0 106.667-37.333 197.333-112 272s-165.333 112-272 112zM512 810.667c62.579 0 118.754-17.25 168.533-51.755s86.046-79.475 108.8-134.912c-14.221 3.554-28.446 6.4-42.667 8.533s-28.446 3.2-42.667 3.2c-87.467 0-161.963-30.763-223.488-92.288s-92.274-136.007-92.245-223.445c0-14.222 1.067-28.445 3.2-42.667s4.978-28.445 8.533-42.667c-55.467 22.755-100.451 59.022-134.955 108.8s-51.741 105.954-51.712 168.533c0 82.487 29.155 152.887 87.467 211.2s128.713 87.467 211.2 87.467z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Dark mode"] - }, - "attrs": [{}], - "properties": { "order": 6, "id": 15, "name": "Dark-mode", "prevSize": 32, "code": 59652 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 4 - }, - { - "icon": { - "paths": [ - "M490.667 128c-198.399 0-366.079 129.28-425.385 308.053l101.12 33.28c44.8-136.107 173.227-234.667 324.265-234.667 83.627 0 159.147 30.72 218.453 80.213l-111.787 111.787h298.667v-298.667l-110.933 110.933c-78.933-68.267-181.333-110.933-294.4-110.933zM810.667 597.333v256c0 47.36-37.973 85.333-85.333 85.333h-85.333c-22.63 0-44.335-8.99-60.339-24.994s-24.994-37.709-24.994-60.339v-256c0-22.63 8.99-44.335 24.994-60.339s37.709-24.994 60.339-24.994h85.333c22.635 0 44.339 8.99 60.339 24.994 16.004 16.004 24.994 37.709 24.994 60.339zM640 597.333v256h85.333v-256h-85.333zM469.333 853.333c0 22.63-8.99 44.335-24.994 60.339-16 16.004-37.706 24.994-60.338 24.994h-170.667v-85.333h170.667v-85.333h-85.333v-85.333h85.333v-85.333h-170.667v-85.333h170.667c22.632 0 44.338 8.99 60.338 24.994 16.004 16.004 24.994 37.709 24.994 60.339v64c0 16.973-6.741 33.254-18.743 45.257s-28.282 18.743-45.255 18.743c16.974 0 33.253 6.741 45.255 18.743s18.743 28.284 18.743 45.257v64z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Fast forward 30"] - }, - "attrs": [{}], - "properties": { "order": 7, "id": 14, "name": "Fast-forward-30", "prevSize": 32, "code": 59653 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 5 - }, - { - "icon": { - "paths": [ - "M597.333 597.333h213.333v85.333h-128v128h-85.333v-213.333zM213.333 597.333h213.333v213.333h-85.333v-128h-128v-85.333zM341.333 213.333h85.333v213.333h-213.333v-85.333h128v-128zM810.667 341.333v85.333h-213.333v-213.333h85.333v128h128z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Fullscreen Exit"] - }, - "attrs": [{}], - "properties": { "order": 8, "id": 13, "name": "Fullscreen-Exit", "prevSize": 32, "code": 59654 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 6 - }, - { - "icon": { - "paths": [ - "M213.333 213.333h213.333v85.333h-128v128h-85.333v-213.333zM597.333 213.333h213.333v213.333h-85.333v-128h-128v-85.333zM725.333 597.333h85.333v213.333h-213.333v-85.333h128v-128zM426.667 725.333v85.333h-213.333v-213.333h85.333v128h128z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Fullscreen"] - }, - "attrs": [{}], - "properties": { "order": 9, "id": 12, "name": "Fullscreen", "prevSize": 32, "code": 59655 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 7 - }, - { - "icon": { - "paths": [ - "M512 896c-98.133 0-183.637-32.525-256.512-97.579s-114.659-146.304-125.355-243.755h87.467c9.955 73.954 42.851 135.113 98.688 183.467s121.075 72.533 195.712 72.533c83.2 0 153.783-28.971 211.755-86.912s86.942-128.525 86.912-211.755c-0.030-83.23-29.001-153.799-86.912-211.712s-128.499-86.898-211.755-86.955c-49.067 0-94.933 11.378-137.6 34.133s-78.578 54.045-107.733 93.867h117.333v85.333h-256v-256h85.333v100.267c36.267-45.511 80.541-80.711 132.821-105.6s107.563-37.333 165.845-37.333c53.333 0 103.296 10.141 149.888 30.421s87.125 47.645 121.6 82.091c34.475 34.446 61.854 74.979 82.133 121.6s30.409 96.585 30.379 149.888c-0.030 53.303-10.155 103.266-30.379 149.888s-47.603 87.155-82.133 121.6c-34.53 34.445-75.063 61.824-121.6 82.133s-96.499 30.434-149.888 30.379zM631.467 691.2l-162.133-162.133v-230.4h85.333v196.267l136.533 136.533-59.733 59.733z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["History"] - }, - "attrs": [{}], - "properties": { "order": 10, "id": 11, "name": "History", "prevSize": 32, "code": 59656 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 8 - }, - { - "icon": { - "paths": [ - "M256 810.667h128v-256h256v256h128v-384l-256-192-256 192v384zM170.667 896v-512l341.333-256 341.333 256v512h-298.667v-256h-85.333v256h-298.667z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Home"] - }, - "attrs": [{}], - "properties": { "order": 11, "id": 10, "name": "Home", "prevSize": 32, "code": 59657 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 9 - }, - { - "icon": { - "paths": [ - "M469.333 384h85.333v-85.333h-85.333zM512 853.333c-188.16 0-341.333-153.173-341.333-341.333s153.173-341.333 341.333-341.333c188.16 0 341.333 153.173 341.333 341.333s-153.173 341.333-341.333 341.333zM512 85.333c-56.030 0-111.513 11.036-163.278 32.478s-98.801 52.87-138.421 92.49c-80.015 80.016-124.968 188.54-124.968 301.699 0 113.161 44.952 221.683 124.968 301.7 39.62 39.62 86.655 71.044 138.421 92.489 51.765 21.44 107.248 32.478 163.278 32.478 113.161 0 221.683-44.954 301.7-124.966 80.013-80.017 124.966-188.54 124.966-301.7 0-56.030-11.038-111.513-32.478-163.278-21.444-51.766-52.868-98.801-92.489-138.421s-86.656-71.048-138.423-92.49c-51.763-21.442-107.247-32.478-163.277-32.478zM469.333 725.333h85.333v-256h-85.333v256z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Information"] - }, - "attrs": [{}], - "properties": { "order": 12, "id": 9, "name": "Information", "prevSize": 32, "code": 59658 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 10 - }, - { - "icon": { - "paths": [ - "M512 640c35.554 0 65.779-12.446 90.667-37.333s37.333-55.113 37.333-90.667c0-35.554-12.446-65.779-37.333-90.667-24.887-24.889-55.113-37.333-90.667-37.333s-65.779 12.445-90.667 37.333c-24.889 24.887-37.333 55.113-37.333 90.667s12.445 65.779 37.333 90.667c24.887 24.887 55.113 37.333 90.667 37.333zM512 725.333c-59.021 0-109.326-20.809-150.912-62.421s-62.393-91.917-62.421-150.912c-0.029-58.995 20.779-109.298 62.421-150.912s91.947-62.421 150.912-62.421c58.965 0 109.282 20.807 150.955 62.421s62.464 91.917 62.379 150.912c-0.085 58.995-20.894 109.312-62.421 150.955s-91.831 62.434-150.912 62.379zM213.333 554.667h-170.667v-85.333h170.667v85.333zM981.333 554.667h-170.667v-85.333h170.667v85.333zM469.333 213.333v-170.667h85.333v170.667h-85.333zM469.333 981.333v-170.667h85.333v170.667h-85.333zM273.067 330.667l-107.733-103.467 60.8-62.933 102.4 106.667-55.467 59.733zM797.867 859.733l-103.467-107.733 56.533-58.667 107.733 103.467-60.8 62.933zM693.333 273.067l103.467-107.733 62.933 60.8-106.667 102.4-59.733-55.467zM164.267 797.867l107.733-103.467 58.667 56.533-103.467 107.733-62.933-60.8z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Light mode"] - }, - "attrs": [{}], - "properties": { "order": 13, "id": 8, "name": "Light-mode", "prevSize": 32, "code": 59659 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 11 - }, - { - "icon": { - "paths": ["M597.333 810.667h170.667v-597.333h-170.667zM256 810.667h170.667v-597.333h-170.667v597.333z"], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Pause"] - }, - "attrs": [{}], - "properties": { "order": 14, "id": 7, "name": "Pause", "prevSize": 32, "code": 59660 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 12 - }, - { - "icon": { - "paths": ["M298.667 176.64v682.666l512-341.333-512-341.333z"], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Play"] - }, - "attrs": [{}], - "properties": { "order": 15, "id": 6, "name": "Play", "prevSize": 32, "code": 59661 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 13 - }, - { - "icon": { - "paths": [ - "M533.333 128c198.4 0 366.080 129.28 425.387 308.053l-101.12 33.28c-44.8-136.107-173.227-234.667-324.267-234.667-83.627 0-159.147 30.72-218.453 80.213l111.787 111.787h-298.667v-298.667l110.933 110.933c78.933-68.267 181.333-110.933 294.4-110.933zM426.667 512v426.667h-85.333v-341.333h-85.333v-85.333h170.667zM512 512h256v85.333h-170.667v85.333h85.333c22.63 0 44.335 8.99 60.339 24.994s24.994 37.709 24.994 60.339v85.333c0 47.36-37.973 85.333-85.333 85.333h-170.667v-85.333h170.667v-85.333h-170.667v-256z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Rewind 15"] - }, - "attrs": [{}], - "properties": { "order": 16, "id": 5, "name": "Rewind-15", "prevSize": 32, "code": 59662 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 14 - }, - { - "icon": { - "paths": [ - "M511.996 640c70.694 0 128-57.306 128-128s-57.306-128-128-128c-70.69 0-127.998 57.306-127.998 128s57.308 128 127.998 128z", - "M377.598 802.133l17.067 136.533h234.669l17.067-136.533c8.533-3.554 17.067-7.821 25.6-12.8s16.708-10.313 24.533-16l125.867 53.333 117.333-202.667-109.867-83.2c1.421-4.979 2.133-9.783 2.133-14.421v-28.757c0-4.638-0.358-9.442-1.067-14.421l109.862-83.2-117.333-202.667-126.929 53.333c-7.795-5.689-15.787-11.022-23.979-16s-16.913-9.245-26.155-12.8l-17.067-136.533h-234.669l-17.067 136.533c-8.533 3.555-17.067 7.822-25.6 12.8s-16.711 10.311-24.533 16l-126.933-53.333-117.333 202.667 109.867 83.2c-0.711 4.979-1.067 9.783-1.067 14.421v28.8c0 4.608 0.355 9.399 1.067 14.379l-109.867 83.2 117.333 202.667 126.933-53.333c7.851 5.687 15.858 11.021 24.021 16s16.868 9.246 26.112 12.8zM553.6 853.333h-84.267l-13.867-113.067c-22.016-5.662-42.455-14.007-61.314-25.045s-36.11-24.734-51.755-41.088l-105.6 44.8-41.6-72.533 91.733-69.333c-3.555-10.667-6.045-21.333-7.467-32s-2.133-21.687-2.133-33.067c0-12.087 0.711-23.467 2.133-34.133s3.911-21.333 7.467-32l-91.733-68.267 41.6-72.533 105.6 43.733c15.673-15.616 32.925-28.942 51.755-39.979s39.268-19.399 61.314-25.088l14.933-113.067h84.267l13.867 113.067c22.071 5.717 42.522 14.080 61.355 25.088 18.829 11.008 36.066 24.69 51.712 41.045l105.6-44.8 41.596 72.533-91.729 69.333c3.554 10.014 6.042 20.51 7.467 31.488 1.421 10.978 2.133 22.174 2.133 33.579s-0.713 22.613-2.133 33.621c-1.425 11.008-3.913 21.491-7.467 31.445l91.729 69.333-41.596 72.533-105.6-43.733c-15.616 15.671-32.853 29.013-51.712 40.021s-39.313 19.358-61.355 25.045l-14.933 113.067z" - ], - "attrs": [{}, {}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Settings"] - }, - "attrs": [{}, {}], - "properties": { "order": 17, "id": 4, "name": "Settings", "prevSize": 32, "code": 59663 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 15 - }, - { - "icon": { - "paths": [ - "M768 938.667c-35.554 0-65.779-12.446-90.667-37.333s-37.333-55.113-37.333-90.667c0-4.979 0.354-10.142 1.067-15.488s1.779-10.142 3.2-14.379l-300.8-174.933c-12.089 10.667-25.6 19.029-40.533 25.088s-30.578 9.075-46.933 9.045c-35.555 0-65.778-12.446-90.667-37.333s-37.333-55.113-37.333-90.667c0-35.554 12.445-65.779 37.333-90.667 24.889-24.889 55.111-37.333 90.667-37.333 16.355 0 32 3.029 46.933 9.088s28.445 14.407 40.533 25.045l300.8-174.933c-1.421-4.267-2.487-9.059-3.2-14.379s-1.067-10.482-1.067-15.488c0-35.555 12.446-65.778 37.333-90.667s55.113-37.333 90.667-37.333c35.554 0 65.779 12.445 90.667 37.333s37.333 55.111 37.333 90.667c0 35.555-12.446 65.778-37.333 90.667s-55.113 37.333-90.667 37.333c-16.354 0-32-3.015-46.933-9.045s-28.446-14.393-40.533-25.088l-300.8 174.933c1.422 4.267 2.489 9.075 3.2 14.421s1.067 10.496 1.067 15.445c0 4.949-0.355 10.112-1.067 15.488s-1.778 10.167-3.2 14.379l300.8 174.933c12.087-10.667 25.6-19.017 40.533-25.045s30.579-9.058 46.933-9.088c35.554 0 65.779 12.446 90.667 37.333s37.333 55.113 37.333 90.667c0 35.554-12.446 65.779-37.333 90.667s-55.113 37.333-90.667 37.333zM768 256c12.087 0 22.229-4.082 30.421-12.245s12.275-18.304 12.245-30.421c-0.030-12.117-4.126-22.243-12.288-30.379s-18.291-12.231-30.379-12.288c-12.087-0.057-22.217 4.039-30.379 12.288s-12.258 18.375-12.288 30.379c-0.030 12.003 4.066 22.144 12.288 30.421s18.347 12.359 30.379 12.245zM256 554.667c12.089 0 22.229-4.096 30.421-12.288s12.274-18.317 12.245-30.379c-0.029-12.062-4.125-22.187-12.288-30.379s-18.29-12.288-30.379-12.288c-12.089 0-22.215 4.096-30.379 12.288s-12.259 18.317-12.288 30.379c-0.029 12.062 4.067 22.199 12.288 30.421s18.347 12.301 30.379 12.245zM768 853.333c12.087 0 22.229-4.096 30.421-12.288s12.275-18.317 12.245-30.379c-0.030-12.062-4.126-22.187-12.288-30.379s-18.291-12.288-30.379-12.288c-12.087 0-22.217 4.096-30.379 12.288s-12.258 18.317-12.288 30.379c-0.030 12.062 4.066 22.199 12.288 30.421s18.347 12.301 30.379 12.245z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Share"] - }, - "attrs": [{}], - "properties": { "order": 18, "id": 3, "name": "Share", "prevSize": 32, "code": 59664 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 16 - }, - { - "icon": { - "paths": [ - "M256 810.667c0 22.63 8.99 44.335 24.994 60.339s37.708 24.994 60.34 24.994h341.333c22.63 0 44.335-8.99 60.339-24.994s24.994-37.709 24.994-60.339v-512h-512v512zM341.333 384h341.333v426.667h-341.333v-426.667zM661.333 170.667l-42.667-42.667h-213.333l-42.667 42.667h-149.333v85.333h597.333v-85.333h-149.333z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Trash"] - }, - "attrs": [{}], - "properties": { "order": 19, "id": 2, "name": "Trash", "prevSize": 32, "code": 59665 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 17 - }, - { - "icon": { - "paths": [ - "M512 170.667l-89.173 89.173 89.173 89.173zM182.187 128l-54.187 54.187 201.813 201.813h-201.813v256h170.667l213.333 213.333v-287.147l181.333 181.76c-28.587 21.76-60.587 39.68-96 49.92v88.32c58.88-13.653 112.213-40.533 157.013-77.227l87.467 87.040 54.187-54.187-384-384zM810.667 512c0 40.107-8.533 77.653-23.040 112.64l64.427 64.427c28.821-54.575 43.904-115.349 43.947-177.067 0-182.613-128-335.36-298.667-374.187v87.893c123.307 36.693 213.333 151.040 213.333 286.293zM704 512c0-75.52-42.667-140.373-106.667-171.947v94.293l104.533 104.533c2.133-8.533 2.133-17.92 2.133-26.88z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["volume Off"] - }, - "attrs": [{}], - "properties": { "order": 20, "id": 1, "name": "Volume-Off", "prevSize": 32, "code": 59666 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 18 - }, - { - "icon": { - "paths": [ - "M597.333 137.812v87.893c123.307 36.693 213.333 151.040 213.333 286.294s-90.027 249.173-213.333 285.867v88.32c170.667-38.827 298.667-191.573 298.667-374.187s-128-335.361-298.667-374.188zM704 512c0-75.52-42.667-140.374-106.667-171.948v342.614c64-30.293 106.667-95.573 106.667-170.667zM128 383.999v256.001h170.667l213.333 213.333v-682.668l-213.333 213.333h-170.667z" - ], - "attrs": [{}], - "isMulticolor": false, - "isMulticolor2": false, - "grid": 0, - "tags": ["Volume"] - }, - "attrs": [{}], - "properties": { "order": 21, "id": 0, "name": "Volume", "prevSize": 32, "code": 59667 }, - "setIdx": 0, - "setId": 2, - "iconIdx": 19 - } - ], - "height": 1024, - "metadata": { "name": "icomoon" }, - "preferences": { - "showGlyphs": true, - "showQuickUse": true, - "showQuickUse2": true, - "showSVGs": true, - "fontPref": { - "prefix": "icon-", - "metadata": { "fontFamily": "icomoon" }, - "metrics": { "emSize": 1024, "baseline": 6.25, "whitespace": 50 }, - "embed": false - }, - "imagePref": { - "prefix": "icon-", - "png": true, - "useClassSelector": true, - "color": 0, - "bgColor": 16777215, - "classSelector": ".icon" - }, - "historySize": 50, - "showCodes": true, - "gridSize": 16 - } -} +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M512 298.667v170.667l-256-213.333 256-213.333v170.667c188.514 0 341.333 152.82 341.333 341.333s-152.819 341.333-341.333 341.333c-188.513 0-341.333-152.819-341.333-341.333h85.333c0 141.385 114.615 256 256 256s256-114.615 256-256c0-141.385-114.615-256-256-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Restart"]},"attrs":[{}],"properties":{"order":22,"id":20,"name":"Restart","prevSize":32,"code":59668},"setIdx":0,"setId":2,"iconIdx":0},{"icon":{"paths":["M853.329 469.333v85.333h-512l234.666 234.667-60.587 60.587-337.92-337.92 337.92-337.922 60.587 60.587-234.666 234.668h512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Arrow Left"]},"attrs":[{}],"properties":{"order":2,"id":19,"name":"Arrow-Left","prevSize":32,"code":59648},"setIdx":0,"setId":2,"iconIdx":1},{"icon":{"paths":["M316.16 366.081l195.84 195.839 195.84-195.839 60.16 60.586-256 256-256-256 60.16-60.586z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Chevron"]},"attrs":[{}],"properties":{"order":3,"id":18,"name":"Chevron","prevSize":32,"code":59649},"setIdx":0,"setId":2,"iconIdx":2},{"icon":{"paths":["M273.067 810.667l-59.733-59.733 238.933-238.933-238.933-238.933 59.733-59.733 238.933 238.933 238.933-238.933 59.733 59.733-238.933 238.933 238.933 238.933-59.733 59.733-238.933-238.933-238.933 238.933z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Close"]},"attrs":[{}],"properties":{"order":4,"id":17,"name":"Close","prevSize":32,"code":59650},"setIdx":0,"setId":2,"iconIdx":3},{"icon":{"paths":["M298.667 768v-682.667h554.667v682.667h-554.667zM384 682.667h384v-512h-384v512zM128 938.667v-682.667h85.333v597.333h469.333v85.333h-554.667z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Content Copy"]},"attrs":[{}],"properties":{"order":5,"id":16,"name":"Content-Copy","prevSize":32,"code":59651},"setIdx":0,"setId":2,"iconIdx":4},{"icon":{"paths":["M512 896c-106.667 0-197.333-37.333-272-112s-112-165.333-112-272c0-106.667 37.333-197.333 112-272s165.333-112 272-112c9.954 0 19.742 0.355 29.355 1.067s19.029 1.778 28.245 3.2c-29.154 20.622-52.45 47.474-69.888 80.555s-26.142 68.807-26.112 107.179c0 64 22.4 118.4 67.2 163.2s99.2 67.2 163.2 67.2c39.113 0 75.021-8.717 107.733-26.155s59.379-40.717 80-69.845c1.421 9.246 2.487 18.658 3.2 28.245s1.067 19.371 1.067 29.355c0 106.667-37.333 197.333-112 272s-165.333 112-272 112zM512 810.667c62.579 0 118.754-17.25 168.533-51.755s86.046-79.475 108.8-134.912c-14.221 3.554-28.446 6.4-42.667 8.533s-28.446 3.2-42.667 3.2c-87.467 0-161.963-30.763-223.488-92.288s-92.274-136.007-92.245-223.445c0-14.222 1.067-28.445 3.2-42.667s4.978-28.445 8.533-42.667c-55.467 22.755-100.451 59.022-134.955 108.8s-51.741 105.954-51.712 168.533c0 82.487 29.155 152.887 87.467 211.2s128.713 87.467 211.2 87.467z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Dark mode"]},"attrs":[{}],"properties":{"order":6,"id":15,"name":"Dark-mode","prevSize":32,"code":59652},"setIdx":0,"setId":2,"iconIdx":5},{"icon":{"paths":["M490.667 128c-198.399 0-366.079 129.28-425.385 308.053l101.12 33.28c44.8-136.107 173.227-234.667 324.265-234.667 83.627 0 159.147 30.72 218.453 80.213l-111.787 111.787h298.667v-298.667l-110.933 110.933c-78.933-68.267-181.333-110.933-294.4-110.933zM810.667 597.333v256c0 47.36-37.973 85.333-85.333 85.333h-85.333c-22.63 0-44.335-8.99-60.339-24.994s-24.994-37.709-24.994-60.339v-256c0-22.63 8.99-44.335 24.994-60.339s37.709-24.994 60.339-24.994h85.333c22.635 0 44.339 8.99 60.339 24.994 16.004 16.004 24.994 37.709 24.994 60.339zM640 597.333v256h85.333v-256h-85.333zM469.333 853.333c0 22.63-8.99 44.335-24.994 60.339-16 16.004-37.706 24.994-60.338 24.994h-170.667v-85.333h170.667v-85.333h-85.333v-85.333h85.333v-85.333h-170.667v-85.333h170.667c22.632 0 44.338 8.99 60.338 24.994 16.004 16.004 24.994 37.709 24.994 60.339v64c0 16.973-6.741 33.254-18.743 45.257s-28.282 18.743-45.255 18.743c16.974 0 33.253 6.741 45.255 18.743s18.743 28.284 18.743 45.257v64z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Fast forward 30"]},"attrs":[{}],"properties":{"order":7,"id":14,"name":"Fast-forward-30","prevSize":32,"code":59653},"setIdx":0,"setId":2,"iconIdx":6},{"icon":{"paths":["M597.333 597.333h213.333v85.333h-128v128h-85.333v-213.333zM213.333 597.333h213.333v213.333h-85.333v-128h-128v-85.333zM341.333 213.333h85.333v213.333h-213.333v-85.333h128v-128zM810.667 341.333v85.333h-213.333v-213.333h85.333v128h128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Fullscreen Exit"]},"attrs":[{}],"properties":{"order":8,"id":13,"name":"Fullscreen-Exit","prevSize":32,"code":59654},"setIdx":0,"setId":2,"iconIdx":7},{"icon":{"paths":["M213.333 213.333h213.333v85.333h-128v128h-85.333v-213.333zM597.333 213.333h213.333v213.333h-85.333v-128h-128v-85.333zM725.333 597.333h85.333v213.333h-213.333v-85.333h128v-128zM426.667 725.333v85.333h-213.333v-213.333h85.333v128h128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Fullscreen"]},"attrs":[{}],"properties":{"order":9,"id":12,"name":"Fullscreen","prevSize":32,"code":59655},"setIdx":0,"setId":2,"iconIdx":8},{"icon":{"paths":["M512 896c-98.133 0-183.637-32.525-256.512-97.579s-114.659-146.304-125.355-243.755h87.467c9.955 73.954 42.851 135.113 98.688 183.467s121.075 72.533 195.712 72.533c83.2 0 153.783-28.971 211.755-86.912s86.942-128.525 86.912-211.755c-0.030-83.23-29.001-153.799-86.912-211.712s-128.499-86.898-211.755-86.955c-49.067 0-94.933 11.378-137.6 34.133s-78.578 54.045-107.733 93.867h117.333v85.333h-256v-256h85.333v100.267c36.267-45.511 80.541-80.711 132.821-105.6s107.563-37.333 165.845-37.333c53.333 0 103.296 10.141 149.888 30.421s87.125 47.645 121.6 82.091c34.475 34.446 61.854 74.979 82.133 121.6s30.409 96.585 30.379 149.888c-0.030 53.303-10.155 103.266-30.379 149.888s-47.603 87.155-82.133 121.6c-34.53 34.445-75.063 61.824-121.6 82.133s-96.499 30.434-149.888 30.379zM631.467 691.2l-162.133-162.133v-230.4h85.333v196.267l136.533 136.533-59.733 59.733z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["History"]},"attrs":[{}],"properties":{"order":10,"id":11,"name":"History","prevSize":32,"code":59656},"setIdx":0,"setId":2,"iconIdx":9},{"icon":{"paths":["M256 810.667h128v-256h256v256h128v-384l-256-192-256 192v384zM170.667 896v-512l341.333-256 341.333 256v512h-298.667v-256h-85.333v256h-298.667z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Home"]},"attrs":[{}],"properties":{"order":11,"id":10,"name":"Home","prevSize":32,"code":59657},"setIdx":0,"setId":2,"iconIdx":10},{"icon":{"paths":["M469.333 384h85.333v-85.333h-85.333zM512 853.333c-188.16 0-341.333-153.173-341.333-341.333s153.173-341.333 341.333-341.333c188.16 0 341.333 153.173 341.333 341.333s-153.173 341.333-341.333 341.333zM512 85.333c-56.030 0-111.513 11.036-163.278 32.478s-98.801 52.87-138.421 92.49c-80.015 80.016-124.968 188.54-124.968 301.699 0 113.161 44.952 221.683 124.968 301.7 39.62 39.62 86.655 71.044 138.421 92.489 51.765 21.44 107.248 32.478 163.278 32.478 113.161 0 221.683-44.954 301.7-124.966 80.013-80.017 124.966-188.54 124.966-301.7 0-56.030-11.038-111.513-32.478-163.278-21.444-51.766-52.868-98.801-92.489-138.421s-86.656-71.048-138.423-92.49c-51.763-21.442-107.247-32.478-163.277-32.478zM469.333 725.333h85.333v-256h-85.333v256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Information"]},"attrs":[{}],"properties":{"order":12,"id":9,"name":"Information","prevSize":32,"code":59658},"setIdx":0,"setId":2,"iconIdx":11},{"icon":{"paths":["M512 640c35.554 0 65.779-12.446 90.667-37.333s37.333-55.113 37.333-90.667c0-35.554-12.446-65.779-37.333-90.667-24.887-24.889-55.113-37.333-90.667-37.333s-65.779 12.445-90.667 37.333c-24.889 24.887-37.333 55.113-37.333 90.667s12.445 65.779 37.333 90.667c24.887 24.887 55.113 37.333 90.667 37.333zM512 725.333c-59.021 0-109.326-20.809-150.912-62.421s-62.393-91.917-62.421-150.912c-0.029-58.995 20.779-109.298 62.421-150.912s91.947-62.421 150.912-62.421c58.965 0 109.282 20.807 150.955 62.421s62.464 91.917 62.379 150.912c-0.085 58.995-20.894 109.312-62.421 150.955s-91.831 62.434-150.912 62.379zM213.333 554.667h-170.667v-85.333h170.667v85.333zM981.333 554.667h-170.667v-85.333h170.667v85.333zM469.333 213.333v-170.667h85.333v170.667h-85.333zM469.333 981.333v-170.667h85.333v170.667h-85.333zM273.067 330.667l-107.733-103.467 60.8-62.933 102.4 106.667-55.467 59.733zM797.867 859.733l-103.467-107.733 56.533-58.667 107.733 103.467-60.8 62.933zM693.333 273.067l103.467-107.733 62.933 60.8-106.667 102.4-59.733-55.467zM164.267 797.867l107.733-103.467 58.667 56.533-103.467 107.733-62.933-60.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Light mode"]},"attrs":[{}],"properties":{"order":13,"id":8,"name":"Light-mode","prevSize":32,"code":59659},"setIdx":0,"setId":2,"iconIdx":12},{"icon":{"paths":["M597.333 810.667h170.667v-597.333h-170.667zM256 810.667h170.667v-597.333h-170.667v597.333z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Pause"]},"attrs":[{}],"properties":{"order":14,"id":7,"name":"Pause","prevSize":32,"code":59660},"setIdx":0,"setId":2,"iconIdx":13},{"icon":{"paths":["M298.667 176.64v682.666l512-341.333-512-341.333z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Play"]},"attrs":[{}],"properties":{"order":15,"id":6,"name":"Play","prevSize":32,"code":59661},"setIdx":0,"setId":2,"iconIdx":14},{"icon":{"paths":["M533.333 128c198.4 0 366.080 129.28 425.387 308.053l-101.12 33.28c-44.8-136.107-173.227-234.667-324.267-234.667-83.627 0-159.147 30.72-218.453 80.213l111.787 111.787h-298.667v-298.667l110.933 110.933c78.933-68.267 181.333-110.933 294.4-110.933zM426.667 512v426.667h-85.333v-341.333h-85.333v-85.333h170.667zM512 512h256v85.333h-170.667v85.333h85.333c22.63 0 44.335 8.99 60.339 24.994s24.994 37.709 24.994 60.339v85.333c0 47.36-37.973 85.333-85.333 85.333h-170.667v-85.333h170.667v-85.333h-170.667v-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Rewind 15"]},"attrs":[{}],"properties":{"order":16,"id":5,"name":"Rewind-15","prevSize":32,"code":59662},"setIdx":0,"setId":2,"iconIdx":15},{"icon":{"paths":["M511.996 640c70.694 0 128-57.306 128-128s-57.306-128-128-128c-70.69 0-127.998 57.306-127.998 128s57.308 128 127.998 128z","M377.598 802.133l17.067 136.533h234.669l17.067-136.533c8.533-3.554 17.067-7.821 25.6-12.8s16.708-10.313 24.533-16l125.867 53.333 117.333-202.667-109.867-83.2c1.421-4.979 2.133-9.783 2.133-14.421v-28.757c0-4.638-0.358-9.442-1.067-14.421l109.862-83.2-117.333-202.667-126.929 53.333c-7.795-5.689-15.787-11.022-23.979-16s-16.913-9.245-26.155-12.8l-17.067-136.533h-234.669l-17.067 136.533c-8.533 3.555-17.067 7.822-25.6 12.8s-16.711 10.311-24.533 16l-126.933-53.333-117.333 202.667 109.867 83.2c-0.711 4.979-1.067 9.783-1.067 14.421v28.8c0 4.608 0.355 9.399 1.067 14.379l-109.867 83.2 117.333 202.667 126.933-53.333c7.851 5.687 15.858 11.021 24.021 16s16.868 9.246 26.112 12.8zM553.6 853.333h-84.267l-13.867-113.067c-22.016-5.662-42.455-14.007-61.314-25.045s-36.11-24.734-51.755-41.088l-105.6 44.8-41.6-72.533 91.733-69.333c-3.555-10.667-6.045-21.333-7.467-32s-2.133-21.687-2.133-33.067c0-12.087 0.711-23.467 2.133-34.133s3.911-21.333 7.467-32l-91.733-68.267 41.6-72.533 105.6 43.733c15.673-15.616 32.925-28.942 51.755-39.979s39.268-19.399 61.314-25.088l14.933-113.067h84.267l13.867 113.067c22.071 5.717 42.522 14.080 61.355 25.088 18.829 11.008 36.066 24.69 51.712 41.045l105.6-44.8 41.596 72.533-91.729 69.333c3.554 10.014 6.042 20.51 7.467 31.488 1.421 10.978 2.133 22.174 2.133 33.579s-0.713 22.613-2.133 33.621c-1.425 11.008-3.913 21.491-7.467 31.445l91.729 69.333-41.596 72.533-105.6-43.733c-15.616 15.671-32.853 29.013-51.712 40.021s-39.313 19.358-61.355 25.045l-14.933 113.067z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Settings"]},"attrs":[{},{}],"properties":{"order":17,"id":4,"name":"Settings","prevSize":32,"code":59663},"setIdx":0,"setId":2,"iconIdx":16},{"icon":{"paths":["M768 938.667c-35.554 0-65.779-12.446-90.667-37.333s-37.333-55.113-37.333-90.667c0-4.979 0.354-10.142 1.067-15.488s1.779-10.142 3.2-14.379l-300.8-174.933c-12.089 10.667-25.6 19.029-40.533 25.088s-30.578 9.075-46.933 9.045c-35.555 0-65.778-12.446-90.667-37.333s-37.333-55.113-37.333-90.667c0-35.554 12.445-65.779 37.333-90.667 24.889-24.889 55.111-37.333 90.667-37.333 16.355 0 32 3.029 46.933 9.088s28.445 14.407 40.533 25.045l300.8-174.933c-1.421-4.267-2.487-9.059-3.2-14.379s-1.067-10.482-1.067-15.488c0-35.555 12.446-65.778 37.333-90.667s55.113-37.333 90.667-37.333c35.554 0 65.779 12.445 90.667 37.333s37.333 55.111 37.333 90.667c0 35.555-12.446 65.778-37.333 90.667s-55.113 37.333-90.667 37.333c-16.354 0-32-3.015-46.933-9.045s-28.446-14.393-40.533-25.088l-300.8 174.933c1.422 4.267 2.489 9.075 3.2 14.421s1.067 10.496 1.067 15.445c0 4.949-0.355 10.112-1.067 15.488s-1.778 10.167-3.2 14.379l300.8 174.933c12.087-10.667 25.6-19.017 40.533-25.045s30.579-9.058 46.933-9.088c35.554 0 65.779 12.446 90.667 37.333s37.333 55.113 37.333 90.667c0 35.554-12.446 65.779-37.333 90.667s-55.113 37.333-90.667 37.333zM768 256c12.087 0 22.229-4.082 30.421-12.245s12.275-18.304 12.245-30.421c-0.030-12.117-4.126-22.243-12.288-30.379s-18.291-12.231-30.379-12.288c-12.087-0.057-22.217 4.039-30.379 12.288s-12.258 18.375-12.288 30.379c-0.030 12.003 4.066 22.144 12.288 30.421s18.347 12.359 30.379 12.245zM256 554.667c12.089 0 22.229-4.096 30.421-12.288s12.274-18.317 12.245-30.379c-0.029-12.062-4.125-22.187-12.288-30.379s-18.29-12.288-30.379-12.288c-12.089 0-22.215 4.096-30.379 12.288s-12.259 18.317-12.288 30.379c-0.029 12.062 4.067 22.199 12.288 30.421s18.347 12.301 30.379 12.245zM768 853.333c12.087 0 22.229-4.096 30.421-12.288s12.275-18.317 12.245-30.379c-0.030-12.062-4.126-22.187-12.288-30.379s-18.291-12.288-30.379-12.288c-12.087 0-22.217 4.096-30.379 12.288s-12.258 18.317-12.288 30.379c-0.030 12.062 4.066 22.199 12.288 30.421s18.347 12.301 30.379 12.245z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Share"]},"attrs":[{}],"properties":{"order":18,"id":3,"name":"Share","prevSize":32,"code":59664},"setIdx":0,"setId":2,"iconIdx":17},{"icon":{"paths":["M256 810.667c0 22.63 8.99 44.335 24.994 60.339s37.708 24.994 60.34 24.994h341.333c22.63 0 44.335-8.99 60.339-24.994s24.994-37.709 24.994-60.339v-512h-512v512zM341.333 384h341.333v426.667h-341.333v-426.667zM661.333 170.667l-42.667-42.667h-213.333l-42.667 42.667h-149.333v85.333h597.333v-85.333h-149.333z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Trash"]},"attrs":[{}],"properties":{"order":19,"id":2,"name":"Trash","prevSize":32,"code":59665},"setIdx":0,"setId":2,"iconIdx":18},{"icon":{"paths":["M512 170.667l-89.173 89.173 89.173 89.173zM182.187 128l-54.187 54.187 201.813 201.813h-201.813v256h170.667l213.333 213.333v-287.147l181.333 181.76c-28.587 21.76-60.587 39.68-96 49.92v88.32c58.88-13.653 112.213-40.533 157.013-77.227l87.467 87.040 54.187-54.187-384-384zM810.667 512c0 40.107-8.533 77.653-23.040 112.64l64.427 64.427c28.821-54.575 43.904-115.349 43.947-177.067 0-182.613-128-335.36-298.667-374.187v87.893c123.307 36.693 213.333 151.040 213.333 286.293zM704 512c0-75.52-42.667-140.373-106.667-171.947v94.293l104.533 104.533c2.133-8.533 2.133-17.92 2.133-26.88z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["volume Off"]},"attrs":[{}],"properties":{"order":20,"id":1,"name":"Volume-Off","prevSize":32,"code":59666},"setIdx":0,"setId":2,"iconIdx":19},{"icon":{"paths":["M597.333 137.812v87.893c123.307 36.693 213.333 151.040 213.333 286.294s-90.027 249.173-213.333 285.867v88.32c170.667-38.827 298.667-191.573 298.667-374.187s-128-335.361-298.667-374.188zM704 512c0-75.52-42.667-140.374-106.667-171.948v342.614c64-30.293 106.667-95.573 106.667-170.667zM128 383.999v256.001h170.667l213.333 213.333v-682.668l-213.333 213.333h-170.667z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Volume"]},"attrs":[{}],"properties":{"order":21,"id":0,"name":"Volume","prevSize":32,"code":59667},"setIdx":0,"setId":2,"iconIdx":20}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16}} \ No newline at end of file diff --git a/OwnTube.tv/components/FocusWrapper.tsx b/OwnTube.tv/components/FocusWrapper.tsx new file mode 100644 index 0000000..dc66657 --- /dev/null +++ b/OwnTube.tv/components/FocusWrapper.tsx @@ -0,0 +1,12 @@ +import { FC, PropsWithChildren } from "react"; +import { useIsFocused } from "@react-navigation/native"; + +export const FocusWrapper: FC = ({ children }) => { + const isFocused = useIsFocused(); + + if (!isFocused) { + return null; + } + + return <>{children}; +}; diff --git a/OwnTube.tv/components/Typography.tsx b/OwnTube.tv/components/Typography.tsx index 2c990e6..710d172 100644 --- a/OwnTube.tv/components/Typography.tsx +++ b/OwnTube.tv/components/Typography.tsx @@ -1,31 +1,50 @@ -import { PropsWithChildren } from "react"; +import { PropsWithChildren, useMemo } from "react"; import { Text, TextProps } from "react-native"; import { useTheme } from "@react-navigation/native"; -import { fontFamilies, typography } from "../theme"; +import { fontFamilies, fontSizes, fontWeights, lineHeights, spacing } from "../theme"; export const Typography = ( props: PropsWithChildren< TextProps & { color?: string; - fontSize?: number; + fontSize?: keyof typeof fontSizes; + fontWeight?: keyof typeof fontWeights; hasOuterGlow?: boolean; } >, ) => { const { colors } = useTheme(); + const { fontSize, lineHeight } = useMemo(() => { + if (!props.fontSize) { + return { fontSize: fontSizes.sizeMd, lineHeight: lineHeights.sizeMd }; + } + + return { fontSize: fontSizes[props.fontSize], lineHeight: lineHeights[props.fontSize] }; + }, [props.fontSize]); + + const fontWeight = useMemo(() => { + if (!props.fontWeight) { + return fontWeights.Regular; + } + + return fontWeights[props.fontWeight]; + }, [props.fontWeight]); + return ( {props.children} diff --git a/OwnTube.tv/components/VideoControlsOverlay/VideoControlsOverlay.tsx b/OwnTube.tv/components/VideoControlsOverlay/VideoControlsOverlay.tsx index 87ae774..5f8a320 100644 --- a/OwnTube.tv/components/VideoControlsOverlay/VideoControlsOverlay.tsx +++ b/OwnTube.tv/components/VideoControlsOverlay/VideoControlsOverlay.tsx @@ -1,17 +1,24 @@ -import { PropsWithChildren, useMemo } from "react"; -import { Dimensions, Pressable, StyleSheet, View } from "react-native"; +import { PropsWithChildren, useMemo, useState } from "react"; +import { Pressable, StyleSheet, View } from "react-native"; import { useTheme } from "@react-navigation/native"; -import { ScrubBar } from "./components/ScrubBar"; import { Typography } from "../Typography"; import { getHumanReadableDuration } from "../../utils"; -import { typography } from "../../theme"; -import { useNavigation } from "expo-router"; -import { DeviceCapabilitiesModal } from "../DeviceCapabilitiesModal"; -import { IcoMoonIcon } from "../IcoMoonIcon"; +import { Link, useNavigation } from "expo-router"; +import { VolumeControl } from "./components/VolumeControl"; +import * as Device from "expo-device"; +import { DeviceType } from "expo-device"; +import { colors, spacing } from "../../theme"; +import { PlayerButton } from "./components/PlayerButton"; +import { ShareButton } from "./components/ShareButton"; +import { TextLink } from "./components/TextLink"; +import { ScrubBar } from "./components/ScrubBar"; +import { LinearGradient } from "expo-linear-gradient"; +import Animated, { SlideInDown, SlideInUp, SlideOutDown, SlideOutUp, FadeIn, FadeOut } from "react-native-reanimated"; +import { useTranslation } from "react-i18next"; interface VideoControlsOverlayProps { isVisible: boolean; - onOverlayPress: () => void; + onOverlayPress?: () => void; isPlaying?: boolean; handlePlayPause: () => void; handleRW: (s: number) => void; @@ -25,6 +32,11 @@ interface VideoControlsOverlayProps { handleReplay: () => void; handleJumpTo: (position: number) => void; title?: string; + channelName?: string; + handleVolumeControl: (volume: number) => void; + volume: number; + toggleFullscreen: () => void; + isFullscreen: boolean; } export const VideoControlsOverlay = ({ @@ -44,19 +56,19 @@ export const VideoControlsOverlay = ({ handleReplay, handleJumpTo, title, + channelName, + handleVolumeControl, + volume, + toggleFullscreen, + isFullscreen, }: PropsWithChildren) => { + const { t } = useTranslation(); const { colors } = useTheme(); const navigation = useNavigation(); - - const uiScale = useMemo(() => { - const { width, height } = Dimensions.get("window"); - const isHorizontal = width > height; - - return isHorizontal ? 1 : 0.5; - }, []); + const [isSeekBarFocused, setIsSeekBarFocused] = useState(false); const centralIconName = useMemo(() => { - return isPlaying ? "Pause" : shouldReplay ? "Reload" : "Play"; + return isPlaying ? "Pause" : shouldReplay ? "Restart" : "Play"; }, [isPlaying, shouldReplay]); const { percentageAvailable, percentagePosition } = useMemo(() => { @@ -66,59 +78,122 @@ export const VideoControlsOverlay = ({ }; }, [availableDuration, duration, position]); + const isMobile = Device.deviceType !== DeviceType.DESKTOP; + return ( - + // @ts-expect-error web cursor options not included in React Native core + {isVisible ? ( - - - - - - - + + + + + + + + {channelName} + + + + {title} + + {}} isMobile={isMobile} /> + + + + {}} isMobile={isMobile} /> + {}} icon="Settings" /> + + + + {isMobile && ( + + handleRW(15)} icon="Rewind-15" /> + + handleFF(30)} icon="Fast-forward-30" /> + + )} + + + setIsSeekBarFocused(true)} + onHoverOut={() => setIsSeekBarFocused(false)} + style={styles.scrubBarContainer} > - {title} - - - - - - - - - - - - handleRW(15)}> - - - - - - handleFF(30)}> - + - - - - - {getHumanReadableDuration(position)} - - - - {getHumanReadableDuration(duration)} - - + + + {!isMobile && ( + <> + + handleRW(15)} icon="Rewind-15" /> + handleFF(30)} icon="Fast-forward-30" /> + + + )} + + {`${getHumanReadableDuration(position)} / ${getHumanReadableDuration(duration)}`} + + + + + + ) : null} {children} @@ -127,22 +202,36 @@ export const VideoControlsOverlay = ({ }; const styles = StyleSheet.create({ + animatedBottomContainer: { bottom: 0, left: 0, position: "absolute", width: "100%" }, + animatedTopContainer: { left: 0, position: "absolute", top: 0, width: "100%", zIndex: 1 }, bottomControlsContainer: { alignItems: "center", - bottom: 0, + cursor: "auto", + justifyContent: "flex-end", + paddingHorizontal: spacing.sm, + width: "100%", + }, + bottomRowContainer: { + alignItems: "center", + alignSelf: "flex-start", flexDirection: "row", - height: "20%", - justifyContent: "center", + justifyContent: "space-between", + width: "100%", + }, + bottomRowControlsContainer: { alignItems: "center", flexDirection: "row" }, + contentContainer: { + flex: 1, + height: "100%", left: 0, position: "absolute", + top: 0, width: "100%", + zIndex: 1, }, - contentContainer: { flex: 1, height: "100%", left: 0, position: "absolute", top: 0, width: "100%", zIndex: 1 }, - goBackContainer: { justifyContent: "center" }, overlay: { alignItems: "center", alignSelf: "center", - cursor: "auto", + backgroundColor: colors.dark.black100, display: "flex", height: "100%", justifyContent: "center", @@ -150,34 +239,34 @@ const styles = StyleSheet.create({ }, playbackControlsContainer: { alignItems: "center", + flexDirection: "row", flex: 1, + gap: spacing.xl, height: "100%", justifyContent: "center", + position: "relative", width: "100%", + zIndex: 2, }, - timeBlockLeft: { - left: "3%", - position: "absolute", - userSelect: "none", - }, - timeBlockRight: { - position: "absolute", - right: "3%", + scrubBarContainer: { height: spacing.md, width: "100%" }, + timingContainer: { + height: 48, + justifyContent: "center", + lineHeight: 48, + textAlign: "center", + textAlignVertical: "center", userSelect: "none", }, - title: { fontWeight: "bold", maxWidth: "78%" }, topControlsContainer: { - alignItems: "center", + alignItems: "flex-start", flexDirection: "row", - height: "20%", + gap: spacing.lg, justifyContent: "space-between", - left: 0, - paddingHorizontal: "5%", - position: "absolute", - top: 0, + paddingHorizontal: spacing.sm, + paddingTop: spacing.xl, width: "100%", - zIndex: 1, }, - topLeftControls: { flexDirection: "row", gap: 24, width: "80%" }, - topRightControls: { alignItems: "center", flexDirection: "row", gap: 24, justifyContent: "flex-end", width: "20%" }, + topLeftControls: { flexDirection: "row", gap: spacing.sm, maxWidth: 600, width: "60%" }, + topRightControls: { alignItems: "center", flexDirection: "row" }, + videoInfoContainer: { gap: spacing.md, width: "100%" }, }); diff --git a/OwnTube.tv/components/VideoControlsOverlay/components/PlayerButton.tsx b/OwnTube.tv/components/VideoControlsOverlay/components/PlayerButton.tsx new file mode 100644 index 0000000..efa6430 --- /dev/null +++ b/OwnTube.tv/components/VideoControlsOverlay/components/PlayerButton.tsx @@ -0,0 +1,44 @@ +import { useState } from "react"; +import { spacing } from "../../../theme"; +import { IcoMoonIcon } from "../../IcoMoonIcon"; +import { Pressable, StyleSheet } from "react-native"; +import { useTheme } from "@react-navigation/native"; + +interface PlayerButtonProps { + onPress: () => void; + icon: string; + onHoverIn?: () => void; + onHoverOut?: () => void; +} + +export const PlayerButton = ({ onPress, icon, onHoverIn, onHoverOut }: PlayerButtonProps) => { + const { colors } = useTheme(); + const [isHovered, setIsHovered] = useState(false); + + const handleHoverIn = () => { + onHoverIn?.(); + setIsHovered(true); + }; + + const handleHoverOut = () => { + onHoverOut?.(); + setIsHovered(false); + }; + + return ( + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: "center", + flexDirection: "row", + height: 48, + justifyContent: "center", + padding: spacing.md, + width: 48, + }, +}); diff --git a/OwnTube.tv/components/VideoControlsOverlay/components/ScrubBar.tsx b/OwnTube.tv/components/VideoControlsOverlay/components/ScrubBar.tsx index cd0585f..3ee4ccb 100644 --- a/OwnTube.tv/components/VideoControlsOverlay/components/ScrubBar.tsx +++ b/OwnTube.tv/components/VideoControlsOverlay/components/ScrubBar.tsx @@ -4,17 +4,30 @@ import { Gesture, GestureDetector } from "react-native-gesture-handler"; import { useEffect, useMemo, useState } from "react"; import { Typography } from "../../Typography"; import { getHumanReadableDuration } from "../../../utils"; +import { borderRadius, spacing } from "../../../theme"; interface ScrubBarProps { - percentageAvailable: number; percentagePosition: number; + percentageAvailable?: number; onDrag: (position: number) => void; - duration: number; + length: number; + isExpanded: boolean; + variant: "volume" | "seek"; } -const INDICATOR_SIZE = 16; +const INDICATOR_SIZE = 12; +const HALF_INDICATOR_SIZE = INDICATOR_SIZE / 2; +const SEEK_HINT_OFFSET = 26; +const SEEK_HINT_COLOR = "#151E29"; -export const ScrubBar = ({ percentageAvailable, percentagePosition, onDrag, duration }: ScrubBarProps) => { +export const ScrubBar = ({ + percentageAvailable, + percentagePosition, + onDrag, + length, + isExpanded, + variant, +}: ScrubBarProps) => { const { colors } = useTheme(); const [visibleWidth, setVisibleWidth] = useState(0); const [isDragging, setIsDragging] = useState(false); @@ -25,15 +38,15 @@ export const ScrubBar = ({ percentageAvailable, percentagePosition, onDrag, dura return; } - setScrubberPosition(x - INDICATOR_SIZE / 2); + setScrubberPosition(x > HALF_INDICATOR_SIZE ? x - HALF_INDICATOR_SIZE : 0); }; const setPosition = (x: number) => { const newX = visibleWidth <= x ? visibleWidth : x < 0 ? 0 : x; - const newPositionRelation = (newX - INDICATOR_SIZE / 2) / visibleWidth; + const newPositionRelation = (newX - HALF_INDICATOR_SIZE) / visibleWidth; - onDrag(Math.floor(newPositionRelation * duration)); + onDrag(Math.floor(newPositionRelation * length)); }; const pan = Gesture.Pan() @@ -55,8 +68,31 @@ export const ScrubBar = ({ percentageAvailable, percentagePosition, onDrag, dura }, [percentagePosition, visibleWidth]); const seekHint = useMemo(() => { - return getHumanReadableDuration(duration * (scrubberPosition / visibleWidth)); - }, [scrubberPosition, visibleWidth, duration]); + const newPosition = scrubberPosition - SEEK_HINT_OFFSET; + const hintMs = scrubberPosition / visibleWidth; + + return { + text: getHumanReadableDuration(length * (hintMs > 0 ? hintMs : 0)), + position: newPosition < 0 ? 0 : newPosition, + }; + }, [scrubberPosition, visibleWidth, length]); + + const indicatorPosition = useMemo(() => { + return scrubberPosition > HALF_INDICATOR_SIZE ? scrubberPosition - HALF_INDICATOR_SIZE : 0; + }, [scrubberPosition]); + + const colorVariant = useMemo(() => { + return { + volume: { + position: colors.white94, + indicator: colors.white94, + }, + seek: { + position: colors.theme600, + indicator: colors.theme600, + }, + }[variant]; + }, [variant, colors]); return ( @@ -66,41 +102,43 @@ export const ScrubBar = ({ percentageAvailable, percentagePosition, onDrag, dura style={[ styles.scrubBarContainer, { - backgroundColor: colors.background, - borderColor: colors.background, + backgroundColor: colors.white25, }, ]} onLayout={(event) => setVisibleWidth(event.nativeEvent.layout.width)} > - {isDragging && ( + {isDragging && variant === "seek" && ( - {seekHint} + + {seekHint.text} + )} - + {isExpanded && ( + + )} @@ -108,8 +146,9 @@ export const ScrubBar = ({ percentageAvailable, percentagePosition, onDrag, dura style={[ styles.percentagePositionBar, { - backgroundColor: colors.primary, + backgroundColor: colorVariant.position, width: scrubberPosition, + height: isExpanded ? 6 : 4, }, ]} /> @@ -123,50 +162,43 @@ export const ScrubBar = ({ percentageAvailable, percentagePosition, onDrag, dura const styles = StyleSheet.create({ gestureHandlerContainer: { alignItems: "center", - height: 45, + height: spacing.md, position: "relative", - width: "80%", + width: "100%", }, indicator: { - borderRadius: INDICATOR_SIZE, - borderWidth: 1, + borderRadius: borderRadius.radiusSm, height: INDICATOR_SIZE, position: "absolute", - top: -6, + top: -spacing.xs, width: INDICATOR_SIZE, zIndex: 4, }, percentageAvailableBar: { - height: 3, + height: spacing.xs, left: 0, position: "absolute", - top: 1, zIndex: 1, }, percentagePositionBar: { - height: 3, - left: 0, - position: "absolute", - top: 1, zIndex: 2, }, scrubBarContainer: { - borderLeftWidth: 1, - borderRightWidth: 1, + alignItems: "center", flexDirection: "row", - height: 5, + height: spacing.xs, width: "100%", }, scrubBarHitSlop: { alignItems: "center", height: "100%", justifyContent: "center", - width: "95%", + width: "100%", }, seekTime: { - borderRadius: 8, - padding: 8, + borderRadius: borderRadius.radiusMd, + padding: spacing.xs, position: "absolute", - top: -50, + top: -32, }, }); diff --git a/OwnTube.tv/components/VideoControlsOverlay/components/ShareButton.tsx b/OwnTube.tv/components/VideoControlsOverlay/components/ShareButton.tsx new file mode 100644 index 0000000..d87c61f --- /dev/null +++ b/OwnTube.tv/components/VideoControlsOverlay/components/ShareButton.tsx @@ -0,0 +1,44 @@ +import { useState } from "react"; +import { IcoMoonIcon } from "../../IcoMoonIcon"; +import { Typography } from "../../Typography"; +import { Pressable, StyleSheet } from "react-native"; +import { useTheme } from "@react-navigation/native"; +import { spacing } from "../../../theme"; +import { useTranslation } from "react-i18next"; + +interface ShareButtonProps { + onPress: () => void; + isMobile: boolean; +} + +export const ShareButton = ({ onPress, isMobile }: ShareButtonProps) => { + const { t } = useTranslation(); + const { colors } = useTheme(); + const [isHovered, setIsHovered] = useState(false); + + return ( + setIsHovered(true)} + onHoverOut={() => setIsHovered(false)} + > + + {!isMobile && ( + + {t("share")} + + )} + + ); +}; + +const styles = StyleSheet.create({ + container: { alignContent: "center", flexDirection: "row", gap: spacing.md, padding: spacing.md }, + text: { lineHeight: spacing.xl, userSelect: "none" }, +}); diff --git a/OwnTube.tv/components/VideoControlsOverlay/components/TextLink.tsx b/OwnTube.tv/components/VideoControlsOverlay/components/TextLink.tsx new file mode 100644 index 0000000..771d102 --- /dev/null +++ b/OwnTube.tv/components/VideoControlsOverlay/components/TextLink.tsx @@ -0,0 +1,45 @@ +import { useState } from "react"; +import { Typography } from "../../Typography"; +import { IcoMoonIcon } from "../../IcoMoonIcon"; +import { Pressable, StyleSheet } from "react-native"; +import { useTheme } from "@react-navigation/native"; +import { spacing } from "../../../theme"; + +interface TextLinkProps { + isMobile: boolean; + onPress: () => void; + text: string; +} + +export const TextLink = ({ isMobile, onPress, text }: TextLinkProps) => { + const { colors } = useTheme(); + const [isHovered, setIsHovered] = useState(false); + + return ( + setIsHovered(true)} + onHoverOut={() => setIsHovered(false)} + onPress={onPress} + style={styles.container} + > + + {text} + + + + ); +}; + +const styles = StyleSheet.create({ + container: { alignItems: "center", flexDirection: "row", gap: 8 }, + icon: { transform: [{ rotate: "-90deg" }] }, +}); diff --git a/OwnTube.tv/components/VideoControlsOverlay/components/VolumeControl.tsx b/OwnTube.tv/components/VideoControlsOverlay/components/VolumeControl.tsx new file mode 100644 index 0000000..8f2cdc8 --- /dev/null +++ b/OwnTube.tv/components/VideoControlsOverlay/components/VolumeControl.tsx @@ -0,0 +1,55 @@ +import { Pressable, StyleSheet, View } from "react-native"; +import Animated, { useSharedValue, withTiming } from "react-native-reanimated"; +import { PlayerButton } from "./PlayerButton"; +import { ScrubBar } from "./ScrubBar"; + +interface Props { + isMute: boolean; + volume: number; + toggleMute: () => void; + setVolume: (volume: number) => void; +} + +const ANIMATION_DURATION = 350; + +export const VolumeControl = ({ isMute, volume, toggleMute, setVolume }: Props) => { + const width = useSharedValue(0); + + const showVolumeBar = () => { + width.value = withTiming(64, { duration: ANIMATION_DURATION }); + }; + const hideVolumeBar = () => { + width.value = withTiming(0, { duration: ANIMATION_DURATION }); + }; + + return ( + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + animatedContainer: { height: 48, overflow: "hidden" }, + container: { flexDirection: "row" }, + scrubBarContainer: { + alignItems: "center", + height: "100%", + justifyContent: "center", + position: "relative", + width: 52, + zIndex: 10, + }, +}); diff --git a/OwnTube.tv/components/VideoView/VideoView.tsx b/OwnTube.tv/components/VideoView/VideoView.tsx index 5d252cb..2b4ef47 100644 --- a/OwnTube.tv/components/VideoView/VideoView.tsx +++ b/OwnTube.tv/components/VideoView/VideoView.tsx @@ -4,6 +4,11 @@ import { View } from "react-native"; import { VideoControlsOverlay } from "../VideoControlsOverlay"; import { styles } from "./styles"; import { useAppConfigContext } from "../../contexts"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { Gesture, GestureDetector } from "react-native-gesture-handler"; +import * as Device from "expo-device"; +import { DeviceType } from "expo-device"; +import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; export interface VideoViewProps { uri: string; @@ -11,19 +16,29 @@ export interface VideoViewProps { handleSetTimeStamp: (timestamp: number) => void; timestamp?: string; title?: string; + channelName?: string; + toggleFullscreen: () => void; + isFullscreen: boolean; } -const VideoView = ({ uri, testID, handleSetTimeStamp, timestamp, title }: VideoViewProps) => { +const VideoView = ({ + uri, + testID, + handleSetTimeStamp, + timestamp, + title, + channelName, + toggleFullscreen, + isFullscreen, +}: VideoViewProps) => { const videoRef = useRef