diff --git a/CHANGELOG.md b/CHANGELOG.md
index e450d53a..c1b99cd2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,11 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- A dev setting to clear the cache
+
### Fixed
- A bug where bookmarked channels can be duplicated
- A bug where video cast from web app would not play if there's an error dialog on screen
+### Changed
+
+- Font weight to be less bold
+
## [0.23.5] - 2024-05-19
### Fixed
diff --git a/playlet-lib/src/components/Screens/SettingsScreen/ClearCacheControl.bs b/playlet-lib/src/components/Screens/SettingsScreen/ClearCacheControl.bs
new file mode 100644
index 00000000..a3231197
--- /dev/null
+++ b/playlet-lib/src/components/Screens/SettingsScreen/ClearCacheControl.bs
@@ -0,0 +1,27 @@
+import "pkg:/components/Dialog/DialogUtils.bs"
+import "pkg:/source/utils/CacheUtils.bs"
+import "pkg:/source/utils/FocusManagement.bs"
+import "pkg:/source/utils/Locale.bs"
+
+function Init()
+ m.top.focusable = true
+ m.top.itemSpacings = [8]
+ m.button = m.top.findNode("Button")
+ m.button.observeField("buttonSelected", FuncName(OnButtonSelected))
+end function
+
+function OnFocusChange() as void
+ if not m.top.focus
+ return
+ end if
+ NodeSetFocus(m.button, true)
+end function
+
+function BindPreference(_preferences as object, _key as string)
+ ' Do nothing
+end function
+
+function OnButtonSelected()
+ CacheUtils.Clear()
+ DialogUtils.ShowDialog(Tr(Locale.Settings.CacheCleared), Tr(Locale.Generic.Success))
+end function
diff --git a/playlet-lib/src/components/Screens/SettingsScreen/ClearCacheControl.xml b/playlet-lib/src/components/Screens/SettingsScreen/ClearCacheControl.xml
new file mode 100644
index 00000000..3c8c6ff7
--- /dev/null
+++ b/playlet-lib/src/components/Screens/SettingsScreen/ClearCacheControl.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/CacheRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/CacheRouter.bs
new file mode 100644
index 00000000..9eee2716
--- /dev/null
+++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/CacheRouter.bs
@@ -0,0 +1,22 @@
+import "pkg:/source/utils/CacheUtils.bs"
+
+namespace Http
+
+ class CacheRouter extends HttpRouter
+
+ function new()
+ super()
+ end function
+
+ @delete("/api/cache")
+ function ClearCache(context as object) as boolean
+ response = context.response
+
+ CacheUtils.Clear()
+ response.Default(204, "OK")
+ return true
+ end function
+
+ end class
+
+end namespace
diff --git a/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs b/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs
index a76bc7d8..69f12cb7 100644
--- a/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs
+++ b/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs
@@ -1,5 +1,6 @@
import "pkg:/components/parts/AutoBind/OnNodeReadyNoOp.bs"
import "pkg:/components/Web/PlayletWebServer/Middleware/BookmarksRouter.bs"
+import "pkg:/components/Web/PlayletWebServer/Middleware/CacheRouter.bs"
import "pkg:/components/Web/PlayletWebServer/Middleware/DashRouter.bs"
import "pkg:/components/Web/PlayletWebServer/Middleware/DialRouter.bs"
import "pkg:/components/Web/PlayletWebServer/Middleware/HomeLayoutRouter.bs"
@@ -50,6 +51,7 @@ function SetupRoutes(server as object)
server.UseRouter(new Http.SearchHistoryRouter(server))
server.UseRouter(new Http.PlayletLibUrlsRouter(server))
server.UseRouter(new Http.DialRouter(server))
+ server.UseRouter(new Http.CacheRouter())
etags = new Http.EtagUtils()
server.UseRouter(new Http.HttpStaticFilesRouter("/", "libpkg:/www", etags, { staticFiles: true }))
diff --git a/playlet-lib/src/config/preferences.json5 b/playlet-lib/src/config/preferences.json5
index 8d71cf45..c30b9875 100644
--- a/playlet-lib/src/config/preferences.json5
+++ b/playlet-lib/src/config/preferences.json5
@@ -207,6 +207,20 @@
visibility: "web",
svelteComponent: "PlayletLibVersionControl",
},
+ {
+ displayText: "Clear cache",
+ key: "dev.clear_cache",
+ description: "Clear cache from cachefs: and tmp:",
+ visibility: "web",
+ svelteComponent: "ClearCacheControl",
+ },
+ {
+ displayText: "Clear cache",
+ key: "dev.clear_cache",
+ description: "Clear cache from cachefs: and tmp:",
+ visibility: "tv",
+ rokuComponent: "ClearCacheControl",
+ },
],
},
]
diff --git a/playlet-lib/src/locale/en_US/translations.ts b/playlet-lib/src/locale/en_US/translations.ts
index 695a2c8c..e95b839c 100644
--- a/playlet-lib/src/locale/en_US/translations.ts
+++ b/playlet-lib/src/locale/en_US/translations.ts
@@ -1256,5 +1256,17 @@
Rating
+
+
+ Clear cache
+
+
+
+ Clear cache from cachefs: and tmp:
+
+
+
+ Cache cleared.
+
\ No newline at end of file
diff --git a/playlet-lib/src/source/utils/CacheUtils.bs b/playlet-lib/src/source/utils/CacheUtils.bs
new file mode 100644
index 00000000..6c50bc81
--- /dev/null
+++ b/playlet-lib/src/source/utils/CacheUtils.bs
@@ -0,0 +1,10 @@
+import "pkg:/source/AsyncTask/AsyncTask.bs"
+import "pkg:/source/AsyncTask/Tasks.bs"
+
+namespace CacheUtils
+
+ function Clear()
+ AsyncTask.Start(Tasks.ClearCacheTask, invalid)
+ end function
+
+end namespace
diff --git a/playlet-lib/src/source/utils/ClearCacheTask.bs b/playlet-lib/src/source/utils/ClearCacheTask.bs
new file mode 100644
index 00000000..5ffe55c8
--- /dev/null
+++ b/playlet-lib/src/source/utils/ClearCacheTask.bs
@@ -0,0 +1,33 @@
+import "pkg:/source/utils/Logging.bs"
+
+@asynctask
+function ClearCacheTask() as object
+ fs = CreateObject("roFileSystem")
+ if fs = invalid
+ LogError("Failed to create roFileSystem object")
+ return invalid
+ end if
+
+ ClearVolume(fs, "tmp:/")
+ ClearVolume(fs, "cachefs:/")
+
+ return invalid
+end function
+
+function ClearVolume(fs as object, volume as string)
+ items = fs.GetDirectoryListing(volume)
+ for each item in items
+ fullpath = volume + item
+
+ ' Skip logs directory
+ if fullpath = "cachefs:/logs"
+ continue for
+ end if
+
+ if not fs.Delete(fullpath)
+ LogError("Failed to delete:", fullpath)
+ end if
+ end for
+
+ LogInfo("Cleared:", volume)
+end function
diff --git a/playlet-lib/src/source/utils/Locale.bs b/playlet-lib/src/source/utils/Locale.bs
index 31455969..61fb69b9 100644
--- a/playlet-lib/src/source/utils/Locale.bs
+++ b/playlet-lib/src/source/utils/Locale.bs
@@ -283,6 +283,9 @@ namespace Locale
UseDevVideoPlayerDescription = "Enable the dev video player. This is an unfinished video player for testing purposes."
PlayletLibraryVersion = "Playlet Library version"
PlayletLibraryVersionDescription = "The version of Playlet Lib to use. These correspond to tagged releases on Github. Releases that do not have a playlet-lib.zip file are disabled."
+ ClearCache = "Clear cache"
+ ClearCacheDescription = "Clear cache from cachefs: and tmp:"
+ CacheCleared = "Cache cleared."
end enum
@locale
diff --git a/playlet-web/src/lib/Api/InvidiousApi.ts b/playlet-web/src/lib/Api/InvidiousApi.ts
index d64037af..f1c9d9af 100644
--- a/playlet-web/src/lib/Api/InvidiousApi.ts
+++ b/playlet-web/src/lib/Api/InvidiousApi.ts
@@ -265,6 +265,15 @@ export class InvidiousApi {
}
}
+ public static clearCache() {
+ for (let i = localStorage.length - 1; i >= 0; i--) {
+ const key = localStorage.key(i);
+ if (key && key.startsWith("v1:")) {
+ localStorage.removeItem(key);
+ }
+ }
+ }
+
// TODO:P2 use more appropriate cache storage
private getCache(url: string, cacheSeconds: number) {
const cacheKey = this.getCacheKey(url);
diff --git a/playlet-web/src/lib/Api/PlayletApi.ts b/playlet-web/src/lib/Api/PlayletApi.ts
index 2222243b..e7b1de46 100644
--- a/playlet-web/src/lib/Api/PlayletApi.ts
+++ b/playlet-web/src/lib/Api/PlayletApi.ts
@@ -132,6 +132,10 @@ export class PlayletApi {
return await fetch(`${PlayletApi.host()}/api/search-history`, { method: "DELETE" });
}
+ static async clearCache() {
+ return await fetch(`${PlayletApi.host()}/api/cache`, { method: "DELETE" });
+ }
+
static async getBookmarkFeeds() {
const response = await fetch(`${PlayletApi.host()}/api/bookmarks/feeds`);
return await response.json();
diff --git a/playlet-web/src/lib/Screens/Settings/SettingControls/ClearCacheControl.svelte b/playlet-web/src/lib/Screens/Settings/SettingControls/ClearCacheControl.svelte
new file mode 100644
index 00000000..5dca81a2
--- /dev/null
+++ b/playlet-web/src/lib/Screens/Settings/SettingControls/ClearCacheControl.svelte
@@ -0,0 +1,27 @@
+
+
+
+
{$tr(displayText)}
+
{@html $tr(description)}
+
+
diff --git a/playlet-web/src/lib/Screens/Settings/SettingsNode.svelte b/playlet-web/src/lib/Screens/Settings/SettingsNode.svelte
index 0c94e58a..9070d321 100644
--- a/playlet-web/src/lib/Screens/Settings/SettingsNode.svelte
+++ b/playlet-web/src/lib/Screens/Settings/SettingsNode.svelte
@@ -7,6 +7,7 @@
import StringControl from "lib/Screens/Settings/SettingControls/StringControl.svelte";
import NumberControl from "./SettingControls/NumberControl.svelte";
import { tr } from "lib/Stores";
+ import ClearCacheControl from "./SettingControls/ClearCacheControl.svelte";
const textSizes = ["text-2xl", "text-lg", "text-base", "text-sm", "text-xs"];
@@ -30,6 +31,7 @@
const customComponents = {
ClearSearchHistoryControl,
+ ClearCacheControl,
EditHomeScreenControl,
PlayletLibVersionControl,
};