From f8bb43ab9a2384c2203e9c7d81ae7471bde5e377 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 20 Nov 2023 11:05:48 +0100 Subject: [PATCH 01/35] feat: implement search history --- src/routes/Search/Search.js | 3 +++ src/routes/Search/useSearchHistory.d.ts | 2 ++ src/routes/Search/useSearchHistory.js | 10 ++++++++++ src/types/models/Ctx.d.ts | 3 +++ 4 files changed, 18 insertions(+) create mode 100644 src/routes/Search/useSearchHistory.d.ts create mode 100644 src/routes/Search/useSearchHistory.js diff --git a/src/routes/Search/Search.js b/src/routes/Search/Search.js index a2f5b758e..99f7d412e 100644 --- a/src/routes/Search/Search.js +++ b/src/routes/Search/Search.js @@ -8,6 +8,7 @@ const { useTranslation } = require('react-i18next'); const { default: Icon } = require('@stremio/stremio-icons/react'); const { Image, MainNavBars, MetaRow, MetaItem, withCoreSuspender, getVisibleChildrenRange } = require('stremio/common'); const useSearch = require('./useSearch'); +const useSearchHistory = require('./useSearchHistory'); const styles = require('./styles'); const THRESHOLD = 100; @@ -15,6 +16,8 @@ const THRESHOLD = 100; const Search = ({ queryParams }) => { const { t } = useTranslation(); const [search, loadSearchRows] = useSearch(queryParams); + const searchHistory = useSearchHistory(); + console.log(searchHistory); const query = React.useMemo(() => { return search.selected !== null ? search.selected.extra.reduceRight((query, [name, value]) => { diff --git a/src/routes/Search/useSearchHistory.d.ts b/src/routes/Search/useSearchHistory.d.ts new file mode 100644 index 000000000..5049b5046 --- /dev/null +++ b/src/routes/Search/useSearchHistory.d.ts @@ -0,0 +1,2 @@ +declare const useSearchHistory: () => SearchHistory; +export = useSearchHistory; \ No newline at end of file diff --git a/src/routes/Search/useSearchHistory.js b/src/routes/Search/useSearchHistory.js new file mode 100644 index 000000000..5c4833392 --- /dev/null +++ b/src/routes/Search/useSearchHistory.js @@ -0,0 +1,10 @@ +// Copyright (C) 2017-2023 Smart code 203358507 + +const useModelState = require('stremio/common/useModelState'); + +const useSearchHistory = () => { + const { searchHistory } = useModelState({ model: 'ctx' }); + return searchHistory; +}; + +module.exports = useSearchHistory; diff --git a/src/types/models/Ctx.d.ts b/src/types/models/Ctx.d.ts index 54ee1dc4e..ceb291cc7 100644 --- a/src/types/models/Ctx.d.ts +++ b/src/types/models/Ctx.d.ts @@ -56,7 +56,10 @@ type NotificationItem = { videoReleased: string, } +type SearchHistory = string[]; + type Ctx = { profile: Profile, notifications: Notifications, + searchHistory: SearchHistory, }; \ No newline at end of file From fcc3317dc83569f813444c9c3de449f973d34d54 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 20 Nov 2023 11:05:48 +0100 Subject: [PATCH 02/35] feat: implement search history --- src/routes/Search/Search.js | 3 +++ src/routes/Search/useSearchHistory.d.ts | 2 ++ src/routes/Search/useSearchHistory.js | 10 ++++++++++ src/types/models/Ctx.d.ts | 3 +++ 4 files changed, 18 insertions(+) create mode 100644 src/routes/Search/useSearchHistory.d.ts create mode 100644 src/routes/Search/useSearchHistory.js diff --git a/src/routes/Search/Search.js b/src/routes/Search/Search.js index a2f5b758e..99f7d412e 100644 --- a/src/routes/Search/Search.js +++ b/src/routes/Search/Search.js @@ -8,6 +8,7 @@ const { useTranslation } = require('react-i18next'); const { default: Icon } = require('@stremio/stremio-icons/react'); const { Image, MainNavBars, MetaRow, MetaItem, withCoreSuspender, getVisibleChildrenRange } = require('stremio/common'); const useSearch = require('./useSearch'); +const useSearchHistory = require('./useSearchHistory'); const styles = require('./styles'); const THRESHOLD = 100; @@ -15,6 +16,8 @@ const THRESHOLD = 100; const Search = ({ queryParams }) => { const { t } = useTranslation(); const [search, loadSearchRows] = useSearch(queryParams); + const searchHistory = useSearchHistory(); + console.log(searchHistory); const query = React.useMemo(() => { return search.selected !== null ? search.selected.extra.reduceRight((query, [name, value]) => { diff --git a/src/routes/Search/useSearchHistory.d.ts b/src/routes/Search/useSearchHistory.d.ts new file mode 100644 index 000000000..5049b5046 --- /dev/null +++ b/src/routes/Search/useSearchHistory.d.ts @@ -0,0 +1,2 @@ +declare const useSearchHistory: () => SearchHistory; +export = useSearchHistory; \ No newline at end of file diff --git a/src/routes/Search/useSearchHistory.js b/src/routes/Search/useSearchHistory.js new file mode 100644 index 000000000..5c4833392 --- /dev/null +++ b/src/routes/Search/useSearchHistory.js @@ -0,0 +1,10 @@ +// Copyright (C) 2017-2023 Smart code 203358507 + +const useModelState = require('stremio/common/useModelState'); + +const useSearchHistory = () => { + const { searchHistory } = useModelState({ model: 'ctx' }); + return searchHistory; +}; + +module.exports = useSearchHistory; diff --git a/src/types/models/Ctx.d.ts b/src/types/models/Ctx.d.ts index 54ee1dc4e..ceb291cc7 100644 --- a/src/types/models/Ctx.d.ts +++ b/src/types/models/Ctx.d.ts @@ -56,7 +56,10 @@ type NotificationItem = { videoReleased: string, } +type SearchHistory = string[]; + type Ctx = { profile: Profile, notifications: Notifications, + searchHistory: SearchHistory, }; \ No newline at end of file From 4f0d2e3991f2745c10e41d48c18a48d9f3b209ad Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 20 Nov 2023 11:05:48 +0100 Subject: [PATCH 03/35] feat: implement search history --- src/routes/Search/Search.js | 3 +++ src/routes/Search/useSearchHistory.d.ts | 2 ++ src/routes/Search/useSearchHistory.js | 26 +++++++++++++++++++++++++ src/types/models/Ctx.d.ts | 3 +++ 4 files changed, 34 insertions(+) create mode 100644 src/routes/Search/useSearchHistory.d.ts create mode 100644 src/routes/Search/useSearchHistory.js diff --git a/src/routes/Search/Search.js b/src/routes/Search/Search.js index a2f5b758e..99f7d412e 100644 --- a/src/routes/Search/Search.js +++ b/src/routes/Search/Search.js @@ -8,6 +8,7 @@ const { useTranslation } = require('react-i18next'); const { default: Icon } = require('@stremio/stremio-icons/react'); const { Image, MainNavBars, MetaRow, MetaItem, withCoreSuspender, getVisibleChildrenRange } = require('stremio/common'); const useSearch = require('./useSearch'); +const useSearchHistory = require('./useSearchHistory'); const styles = require('./styles'); const THRESHOLD = 100; @@ -15,6 +16,8 @@ const THRESHOLD = 100; const Search = ({ queryParams }) => { const { t } = useTranslation(); const [search, loadSearchRows] = useSearch(queryParams); + const searchHistory = useSearchHistory(); + console.log(searchHistory); const query = React.useMemo(() => { return search.selected !== null ? search.selected.extra.reduceRight((query, [name, value]) => { diff --git a/src/routes/Search/useSearchHistory.d.ts b/src/routes/Search/useSearchHistory.d.ts new file mode 100644 index 000000000..2d317ab4e --- /dev/null +++ b/src/routes/Search/useSearchHistory.d.ts @@ -0,0 +1,2 @@ +declare const useSearchHistory: () => { items: SearchHistory, clear: () => {} }; +export = useSearchHistory; \ No newline at end of file diff --git a/src/routes/Search/useSearchHistory.js b/src/routes/Search/useSearchHistory.js new file mode 100644 index 000000000..99c6f4479 --- /dev/null +++ b/src/routes/Search/useSearchHistory.js @@ -0,0 +1,26 @@ +// Copyright (C) 2017-2023 Smart code 203358507 + +const React = require('react'); +const useModelState = require('stremio/common/useModelState'); +const { useServices } = require('stremio/services'); + +const useSearchHistory = () => { + const { core } = useServices(); + const { searchHistory: items } = useModelState({ model: 'ctx' }); + + const clear = React.useCallback(() => { + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'ClearSearchHistory', + }, + }); + }, []); + + return { + items, + clear, + }; +}; + +module.exports = useSearchHistory; diff --git a/src/types/models/Ctx.d.ts b/src/types/models/Ctx.d.ts index 54ee1dc4e..ceb291cc7 100644 --- a/src/types/models/Ctx.d.ts +++ b/src/types/models/Ctx.d.ts @@ -56,7 +56,10 @@ type NotificationItem = { videoReleased: string, } +type SearchHistory = string[]; + type Ctx = { profile: Profile, notifications: Notifications, + searchHistory: SearchHistory, }; \ No newline at end of file From b906cfdc413a7ca6df0e0d2a7b9c51e62ad34e09 Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Tue, 5 Dec 2023 21:23:01 +0200 Subject: [PATCH 04/35] feature: search history beta v1 --- .../HorizontalNavBar/SearchBar/SearchBar.js | 53 ++++++++++++++-- .../HorizontalNavBar/SearchBar/styles.less | 61 +++++++++++++++++++ src/routes/Search/Search.js | 3 - 3 files changed, 110 insertions(+), 7 deletions(-) diff --git a/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js b/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js index 742c7a692..8f8b31c9c 100644 --- a/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js +++ b/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js @@ -11,11 +11,15 @@ const TextInput = require('stremio/common/TextInput'); const useTorrent = require('stremio/common/useTorrent'); const { withCoreSuspender } = require('stremio/common/CoreSuspender'); const styles = require('./styles'); +const useSearchHistory = require('../../../../routes/Search/useSearchHistory'); const SearchBar = ({ className, query, active }) => { const { t } = useTranslation(); const routeFocused = useRouteFocused(); + const searchHistory = useSearchHistory(); const { createTorrentFromMagnet } = useTorrent(); + const [inputValue, setInputValue] = React.useState(query || ''); + const [historyActive, setHistoryActive] = React.useState(true); const searchInputRef = React.useRef(null); const searchBarOnClick = React.useCallback(() => { if (!active) { @@ -23,6 +27,8 @@ const SearchBar = ({ className, query, active }) => { } }, [active]); const queryInputOnChange = React.useCallback(() => { + setInputValue(searchInputRef.current.value); + setHistoryActive(true); try { createTorrentFromMagnet(searchInputRef.current.value); // eslint-disable-next-line no-empty @@ -32,6 +38,7 @@ const SearchBar = ({ className, query, active }) => { if (searchInputRef.current !== null) { const queryParams = new URLSearchParams([['search', searchInputRef.current.value]]); window.location = `#/search?${queryParams.toString()}`; + setHistoryActive(false); } }, []); React.useEffect(() => { @@ -39,6 +46,18 @@ const SearchBar = ({ className, query, active }) => { searchInputRef.current.focus(); } }, [routeFocused, active, query]); + const queryInputClear = React.useCallback(() => { + searchInputRef.current.value = ''; + setInputValue(''); + window.location = '#/search'; + }, []); + const historyInputSearch = React.useCallback((event) => { + const queryParams = new URLSearchParams([['search', event.target.innerText]]); + window.location = `#/search?${queryParams.toString()}`; + setHistoryActive(false); + + }, []); + return ( + ); }; diff --git a/src/common/NavBar/HorizontalNavBar/SearchBar/styles.less b/src/common/NavBar/HorizontalNavBar/SearchBar/styles.less index 094e6de03..80c6c0190 100644 --- a/src/common/NavBar/HorizontalNavBar/SearchBar/styles.less +++ b/src/common/NavBar/HorizontalNavBar/SearchBar/styles.less @@ -9,6 +9,8 @@ height: var(--search-bar-size); border-radius: var(--search-bar-size); background-color: var(--overlay-color); + position: relative; + overflow: visible; .search-input { flex: 1; @@ -46,4 +48,63 @@ opacity: 0.6; } } + + .search-history { + position: absolute; + width: 100%; + height: auto; + top: 100%; + left: 0; + z-index: 10; + padding: 1rem; + background-color: var(--modal-background-color); + border-radius: var(--border-radius); + + .search-history-actions { + display: flex; + justify-content: space-between; + width: 100%; + opacity: 0.8; + margin-bottom: 1rem; + + .search-history-label { + font-size: 0.8rem; + color: var(--primary-foreground-color); + } + + .search-history-clear { + cursor: pointer; + color: var(--primary-foreground-color); + font-size: 0.8rem; + + &:hover { + opacity: 0.6; + } + } + } + + .search-history-items { + width: 90%; + margin: 0 auto; + display: flex; + justify-content: center; + align-items: flex-start; + flex-direction: column; + gap: 0.5rem 0 +; + .search-history-item { + color: var(--primary-foreground-color); + text-align: left; + text-decoration: none; + padding: 0.5rem 1rem; + border-radius: var(--border-radius); + width: 100%; + cursor: pointer; + + &:hover { + background-color: var(--secondary-background-color); + } + } + } + } } \ No newline at end of file diff --git a/src/routes/Search/Search.js b/src/routes/Search/Search.js index 99f7d412e..a2f5b758e 100644 --- a/src/routes/Search/Search.js +++ b/src/routes/Search/Search.js @@ -8,7 +8,6 @@ const { useTranslation } = require('react-i18next'); const { default: Icon } = require('@stremio/stremio-icons/react'); const { Image, MainNavBars, MetaRow, MetaItem, withCoreSuspender, getVisibleChildrenRange } = require('stremio/common'); const useSearch = require('./useSearch'); -const useSearchHistory = require('./useSearchHistory'); const styles = require('./styles'); const THRESHOLD = 100; @@ -16,8 +15,6 @@ const THRESHOLD = 100; const Search = ({ queryParams }) => { const { t } = useTranslation(); const [search, loadSearchRows] = useSearch(queryParams); - const searchHistory = useSearchHistory(); - console.log(searchHistory); const query = React.useMemo(() => { return search.selected !== null ? search.selected.extra.reduceRight((query, [name, value]) => { From c327412deb334ea91304be83cded2dbff4bd6945 Mon Sep 17 00:00:00 2001 From: kKaskak <117831817+kKaskak@users.noreply.github.com> Date: Wed, 6 Dec 2023 11:38:57 +0200 Subject: [PATCH 05/35] refactor & feature: search history beta v2 --- .../HorizontalNavBar/SearchBar/SearchBar.js | 39 ++++++++++++------- .../HorizontalNavBar/SearchBar/styles.less | 3 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js b/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js index 8f8b31c9c..a9b7555cc 100644 --- a/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js +++ b/src/common/NavBar/HorizontalNavBar/SearchBar/SearchBar.js @@ -21,6 +21,7 @@ const SearchBar = ({ className, query, active }) => { const [inputValue, setInputValue] = React.useState(query || ''); const [historyActive, setHistoryActive] = React.useState(true); const searchInputRef = React.useRef(null); + const searchHistoryRef = React.useRef(null); const searchBarOnClick = React.useCallback(() => { if (!active) { window.location = '#/search'; @@ -28,17 +29,22 @@ const SearchBar = ({ className, query, active }) => { }, [active]); const queryInputOnChange = React.useCallback(() => { setInputValue(searchInputRef.current.value); - setHistoryActive(true); try { createTorrentFromMagnet(searchInputRef.current.value); // eslint-disable-next-line no-empty } catch { } }, []); - const queryInputOnSubmit = React.useCallback(() => { + const queryInputOnSubmit = React.useCallback((event) => { if (searchInputRef.current !== null) { - const queryParams = new URLSearchParams([['search', searchInputRef.current.value]]); - window.location = `#/search?${queryParams.toString()}`; - setHistoryActive(false); + const searchValue = event.target.innerText ? event.target.innerText : searchInputRef.current.value; + if (searchValue) { + const queryParams = new URLSearchParams([['search', searchValue]]); + window.location = `#/search?${queryParams.toString()}`; + setInputValue(searchValue); + if (event.key === 'Enter') { + setHistoryActive(false); + } + } } }, []); React.useEffect(() => { @@ -51,15 +57,17 @@ const SearchBar = ({ className, query, active }) => { setInputValue(''); window.location = '#/search'; }, []); - const historyInputSearch = React.useCallback((event) => { - const queryParams = new URLSearchParams([['search', event.target.innerText]]); - window.location = `#/search?${queryParams.toString()}`; - setHistoryActive(false); - - }, []); + const handleBlur = (event) => { + if (!searchHistoryRef?.current?.contains(event.relatedTarget)) { + setHistoryActive(false); + } + }; + const handleClick = () => { + setHistoryActive((prev) => !prev); + }; return ( -