Spaces:
Paused
Paused
Julian Bilcke
commited on
Commit
·
cc8c83c
1
Parent(s):
a8f27d6
let's promote hugging face projects
Browse files- .gitattributes +1 -0
- assets/ads/README.md +1 -0
- assets/ads/lerobot.gif +3 -0
- assets/ads/smolagents.gif +3 -0
- assets/config/default.yaml +8 -0
- assets/config/tikslop.yaml +69 -0
- build/web/assets/AssetManifest.bin +1 -1
- build/web/assets/AssetManifest.bin.json +1 -1
- build/web/assets/AssetManifest.json +1 -1
- build/web/assets/assets/ads/README.md +1 -0
- build/web/assets/assets/ads/lerobot.gif +3 -0
- build/web/assets/assets/ads/smolagents.gif +3 -0
- build/web/assets/assets/config/custom.yaml +8 -0
- build/web/assets/assets/config/default.yaml +8 -0
- build/web/assets/assets/config/tikslop.yaml +9 -1
- build/web/flutter_bootstrap.js +1 -1
- build/web/flutter_service_worker.js +11 -8
- build/web/index.html +1 -1
- build/web/main.dart.js +0 -0
- lib/config/config.dart +19 -0
- lib/screens/home_screen.dart +16 -10
- lib/widgets/ad_banner.dart +120 -0
- pubspec.yaml +1 -0
.gitattributes
CHANGED
|
@@ -7,3 +7,4 @@
|
|
| 7 |
*.wav filter=lfs diff=lfs merge=lfs -text
|
| 8 |
*.ico filter=lfs diff=lfs merge=lfs -text
|
| 9 |
*.wasm filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 7 |
*.wav filter=lfs diff=lfs merge=lfs -text
|
| 8 |
*.ico filter=lfs diff=lfs merge=lfs -text
|
| 9 |
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.gif filter=lfs diff=lfs merge=lfs -text
|
assets/ads/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Tikslop is a free and open-source project, so the "ads" are used to promote Hugging Face projects, people or spaces.
|
assets/ads/lerobot.gif
ADDED
|
Git LFS Details
|
assets/ads/smolagents.gif
ADDED
|
Git LFS Details
|
assets/config/default.yaml
CHANGED
|
@@ -12,6 +12,14 @@ ui:
|
|
| 12 |
# start playback as soon as we have 1 video over 4 (25%)
|
| 13 |
minimum_buffer_percent_to_start_playback: 25
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
simulation:
|
| 16 |
# how often the description should evolve (in seconds)
|
| 17 |
# setting to 0 disables description evolution
|
|
|
|
| 12 |
# start playback as soon as we have 1 video over 4 (25%)
|
| 13 |
minimum_buffer_percent_to_start_playback: 25
|
| 14 |
|
| 15 |
+
advertising:
|
| 16 |
+
enable_ads: false
|
| 17 |
+
ad_banners:
|
| 18 |
+
- image: assets/ads/lerobot.gif
|
| 19 |
+
link: https://huggingface.co/lerobot
|
| 20 |
+
- image: assets/ads/smolagents.gif
|
| 21 |
+
link: https://huggingface.co/docs/smolagents/index
|
| 22 |
+
|
| 23 |
simulation:
|
| 24 |
# how often the description should evolve (in seconds)
|
| 25 |
# setting to 0 disables description evolution
|
assets/config/tikslop.yaml
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ui:
|
| 2 |
+
product_name: "#tikslop"
|
| 3 |
+
showChatInVideoView: false
|
| 4 |
+
|
| 5 |
+
render_queue:
|
| 6 |
+
# how many clips should be stored in advance
|
| 7 |
+
buffer_size: 3
|
| 8 |
+
|
| 9 |
+
# how many requests for clips can be run in parallel
|
| 10 |
+
max_concurrent_generations: 2
|
| 11 |
+
|
| 12 |
+
# start playback as soon as we have 1 video over 3 (25%)
|
| 13 |
+
minimum_buffer_percent_to_start_playback: 5
|
| 14 |
+
|
| 15 |
+
advertising:
|
| 16 |
+
enable_ads: true
|
| 17 |
+
ad_banners:
|
| 18 |
+
- image: assets/ads/lerobot.gif
|
| 19 |
+
link: https://huggingface.co/lerobot
|
| 20 |
+
- image: assets/ads/smolagents.gif
|
| 21 |
+
link: https://huggingface.co/docs/smolagents/index
|
| 22 |
+
|
| 23 |
+
simulation:
|
| 24 |
+
# how often the description should evolve (in seconds)
|
| 25 |
+
# setting to 0 disables description evolution
|
| 26 |
+
sim_loop_frequency_in_sec: 10
|
| 27 |
+
|
| 28 |
+
# it's OK to use high values here,
|
| 29 |
+
# because some of those values are limited by the backend config,
|
| 30 |
+
# such as the resoltuion or number of frames
|
| 31 |
+
video:
|
| 32 |
+
default_negative_prompt: ""
|
| 33 |
+
|
| 34 |
+
# transition time between each clip
|
| 35 |
+
# the exit (older) clip will see its playback time reduced by this amount
|
| 36 |
+
transition_buffer_duration_ms: 300
|
| 37 |
+
|
| 38 |
+
# how long a generated clip should be, in Duration
|
| 39 |
+
original_clip_duration_seconds: 3
|
| 40 |
+
|
| 41 |
+
# The model works on resolutions that are divisible by 32
|
| 42 |
+
# and number of frames that are divisible by 8 + 1 (e.g. 257).
|
| 43 |
+
#
|
| 44 |
+
# In case the resolution or number of frames are not divisible
|
| 45 |
+
# by 32 or 8 + 1, the input will be padded with -1 and then
|
| 46 |
+
# cropped to the desired resolution and number of frames.
|
| 47 |
+
#
|
| 48 |
+
# The model works best on resolutions under 720 x 1280 and
|
| 49 |
+
# number of frames below 257.
|
| 50 |
+
|
| 51 |
+
# number of inference steps
|
| 52 |
+
# (this is capped by the backend API)
|
| 53 |
+
num_inference_steps: 8
|
| 54 |
+
|
| 55 |
+
guidance_scale: 1.0
|
| 56 |
+
|
| 57 |
+
# original frame-rate of each clip (before we slow them down)
|
| 58 |
+
# in frames per second (so an integer)
|
| 59 |
+
original_clip_frame_rate: 25
|
| 60 |
+
|
| 61 |
+
# (this is capped by the backend API)
|
| 62 |
+
original_clip_width: 1216
|
| 63 |
+
|
| 64 |
+
# (this is capped by the backend API)
|
| 65 |
+
original_clip_height: 672
|
| 66 |
+
|
| 67 |
+
# to do more with less, we slow down the videos (a 3s video will become a 4s video)
|
| 68 |
+
# but if you are GPU rich feel feel to play them back at 100% of their speed!
|
| 69 |
+
clip_playback_speed: 0.7
|
build/web/assets/AssetManifest.bin
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
|
|
|
|
| 1 |
+
|
build/web/assets/AssetManifest.bin.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
"
|
|
|
|
| 1 |
+
"DQgHFGFzc2V0cy9hZHMvUkVBRE1FLm1kDAENAQcFYXNzZXQHFGFzc2V0cy9hZHMvUkVBRE1FLm1kBxZhc3NldHMvYWRzL2xlcm9ib3QuZ2lmDAENAQcFYXNzZXQHFmFzc2V0cy9hZHMvbGVyb2JvdC5naWYHGWFzc2V0cy9hZHMvc21vbGFnZW50cy5naWYMAQ0BBwVhc3NldAcZYXNzZXRzL2Fkcy9zbW9sYWdlbnRzLmdpZgcXYXNzZXRzL2NvbmZpZy9SRUFETUUubWQMAQ0BBwVhc3NldAcXYXNzZXRzL2NvbmZpZy9SRUFETUUubWQHGWFzc2V0cy9jb25maWcvY3VzdG9tLnlhbWwMAQ0BBwVhc3NldAcZYXNzZXRzL2NvbmZpZy9jdXN0b20ueWFtbAcaYXNzZXRzL2NvbmZpZy9kZWZhdWx0LnlhbWwMAQ0BBwVhc3NldAcaYXNzZXRzL2NvbmZpZy9kZWZhdWx0LnlhbWwHGmFzc2V0cy9jb25maWcvdGlrc2xvcC55YW1sDAENAQcFYXNzZXQHGmFzc2V0cy9jb25maWcvdGlrc2xvcC55YW1sBzJwYWNrYWdlcy9jdXBlcnRpbm9faWNvbnMvYXNzZXRzL0N1cGVydGlub0ljb25zLnR0ZgwBDQEHBWFzc2V0BzJwYWNrYWdlcy9jdXBlcnRpbm9faWNvbnMvYXNzZXRzL0N1cGVydGlub0ljb25zLnR0Zg=="
|
build/web/assets/AssetManifest.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
{"assets/config/README.md":["assets/config/README.md"],"assets/config/custom.yaml":["assets/config/custom.yaml"],"assets/config/default.yaml":["assets/config/default.yaml"],"assets/config/tikslop.yaml":["assets/config/tikslop.yaml"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}
|
|
|
|
| 1 |
+
{"assets/ads/README.md":["assets/ads/README.md"],"assets/ads/lerobot.gif":["assets/ads/lerobot.gif"],"assets/ads/smolagents.gif":["assets/ads/smolagents.gif"],"assets/config/README.md":["assets/config/README.md"],"assets/config/custom.yaml":["assets/config/custom.yaml"],"assets/config/default.yaml":["assets/config/default.yaml"],"assets/config/tikslop.yaml":["assets/config/tikslop.yaml"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}
|
build/web/assets/assets/ads/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Tikslop is a free and open-source project, so the "ads" are used to promote Hugging Face projects, people or spaces.
|
build/web/assets/assets/ads/lerobot.gif
ADDED
|
Git LFS Details
|
build/web/assets/assets/ads/smolagents.gif
ADDED
|
Git LFS Details
|
build/web/assets/assets/config/custom.yaml
CHANGED
|
@@ -12,6 +12,14 @@ playback:
|
|
| 12 |
# start playback as soon as we have 1 video over 3
|
| 13 |
minimum_buffer_percent_to_start_playback: 5
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
video:
|
| 16 |
# default negative prompt to filter harmful content
|
| 17 |
default_negative_prompt: "pixelated, deformed, distorted, disfigured, blurry, text, watermark, low quality, gore, sex, blood, nudity, nude, porn, erotic"
|
|
|
|
| 12 |
# start playback as soon as we have 1 video over 3
|
| 13 |
minimum_buffer_percent_to_start_playback: 5
|
| 14 |
|
| 15 |
+
advertising:
|
| 16 |
+
enable_ads: false
|
| 17 |
+
ad_banners:
|
| 18 |
+
- image: assets/ads/lerobot.gif
|
| 19 |
+
link: https://huggingface.co/lerobot
|
| 20 |
+
- image: assets/ads/smolagents.gif
|
| 21 |
+
link: https://huggingface.co/docs/smolagents/index
|
| 22 |
+
|
| 23 |
video:
|
| 24 |
# default negative prompt to filter harmful content
|
| 25 |
default_negative_prompt: "pixelated, deformed, distorted, disfigured, blurry, text, watermark, low quality, gore, sex, blood, nudity, nude, porn, erotic"
|
build/web/assets/assets/config/default.yaml
CHANGED
|
@@ -12,6 +12,14 @@ ui:
|
|
| 12 |
# start playback as soon as we have 1 video over 4 (25%)
|
| 13 |
minimum_buffer_percent_to_start_playback: 25
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
simulation:
|
| 16 |
# how often the description should evolve (in seconds)
|
| 17 |
# setting to 0 disables description evolution
|
|
|
|
| 12 |
# start playback as soon as we have 1 video over 4 (25%)
|
| 13 |
minimum_buffer_percent_to_start_playback: 25
|
| 14 |
|
| 15 |
+
advertising:
|
| 16 |
+
enable_ads: false
|
| 17 |
+
ad_banners:
|
| 18 |
+
- image: assets/ads/lerobot.gif
|
| 19 |
+
link: https://huggingface.co/lerobot
|
| 20 |
+
- image: assets/ads/smolagents.gif
|
| 21 |
+
link: https://huggingface.co/docs/smolagents/index
|
| 22 |
+
|
| 23 |
simulation:
|
| 24 |
# how often the description should evolve (in seconds)
|
| 25 |
# setting to 0 disables description evolution
|
build/web/assets/assets/config/tikslop.yaml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
ui:
|
| 2 |
-
product_name: "#
|
| 3 |
showChatInVideoView: false
|
| 4 |
|
| 5 |
render_queue:
|
|
@@ -12,6 +12,14 @@ render_queue:
|
|
| 12 |
# start playback as soon as we have 1 video over 3 (25%)
|
| 13 |
minimum_buffer_percent_to_start_playback: 5
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
simulation:
|
| 16 |
# how often the description should evolve (in seconds)
|
| 17 |
# setting to 0 disables description evolution
|
|
|
|
| 1 |
ui:
|
| 2 |
+
product_name: "#tikslop"
|
| 3 |
showChatInVideoView: false
|
| 4 |
|
| 5 |
render_queue:
|
|
|
|
| 12 |
# start playback as soon as we have 1 video over 3 (25%)
|
| 13 |
minimum_buffer_percent_to_start_playback: 5
|
| 14 |
|
| 15 |
+
advertising:
|
| 16 |
+
enable_ads: true
|
| 17 |
+
ad_banners:
|
| 18 |
+
- image: assets/ads/lerobot.gif
|
| 19 |
+
link: https://huggingface.co/lerobot
|
| 20 |
+
- image: assets/ads/smolagents.gif
|
| 21 |
+
link: https://huggingface.co/docs/smolagents/index
|
| 22 |
+
|
| 23 |
simulation:
|
| 24 |
# how often the description should evolve (in seconds)
|
| 25 |
# setting to 0 disables description evolution
|
build/web/flutter_bootstrap.js
CHANGED
|
@@ -39,6 +39,6 @@ _flutter.buildConfig = {"engineRevision":"382be0028d370607f76215a9be322e5514b263
|
|
| 39 |
|
| 40 |
_flutter.loader.load({
|
| 41 |
serviceWorkerSettings: {
|
| 42 |
-
serviceWorkerVersion: "
|
| 43 |
}
|
| 44 |
});
|
|
|
|
| 39 |
|
| 40 |
_flutter.loader.load({
|
| 41 |
serviceWorkerSettings: {
|
| 42 |
+
serviceWorkerVersion: "754772620"
|
| 43 |
}
|
| 44 |
});
|
build/web/flutter_service_worker.js
CHANGED
|
@@ -3,12 +3,12 @@ const MANIFEST = 'flutter-app-manifest';
|
|
| 3 |
const TEMP = 'flutter-temp-cache';
|
| 4 |
const CACHE_NAME = 'flutter-app-cache';
|
| 5 |
|
| 6 |
-
const RESOURCES = {"flutter_bootstrap.js": "
|
| 7 |
"version.json": "68350cac7987de2728345c72918dd067",
|
| 8 |
"tikslop.png": "570e1db759046e2d224fef729983634e",
|
| 9 |
"index.html": "3a7029b3672560e7938aab6fa4d30a46",
|
| 10 |
"/": "3a7029b3672560e7938aab6fa4d30a46",
|
| 11 |
-
"main.dart.js": "
|
| 12 |
"tikslop.svg": "26140ba0d153b213b122bc6ebcc17f6c",
|
| 13 |
"flutter.js": "83d881c1dbb6d6bcd6b42e274605b69c",
|
| 14 |
"favicon.png": "c8a183c516004e648a7bac7497c89b97",
|
|
@@ -17,18 +17,21 @@ const RESOURCES = {"flutter_bootstrap.js": "fe329212ac2ce1ff4ecff384592b5d14",
|
|
| 17 |
"icons/Icon-maskable-512.png": "8682b581a7dab984ef4f9b7f21976a64",
|
| 18 |
"icons/Icon-512.png": "8682b581a7dab984ef4f9b7f21976a64",
|
| 19 |
"manifest.json": "c0904388ddaba6a9bd572a80f79a8dcc",
|
| 20 |
-
"assets/AssetManifest.json": "
|
| 21 |
"assets/NOTICES": "f0cfae681e209e19b2b144a9f062a96f",
|
| 22 |
"assets/FontManifest.json": "dc3d03800ccca4601324923c0b1d6d57",
|
| 23 |
-
"assets/AssetManifest.bin.json": "
|
| 24 |
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "33b7d9392238c04c131b6ce224e13711",
|
| 25 |
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
|
| 26 |
-
"assets/AssetManifest.bin": "
|
| 27 |
"assets/fonts/MaterialIcons-Regular.otf": "06b86454c633cc9510ad85ddc0523a91",
|
|
|
|
|
|
|
|
|
|
| 28 |
"assets/assets/config/README.md": "07a87720dd00dd1ca98c9d6884440e31",
|
| 29 |
-
"assets/assets/config/custom.yaml": "
|
| 30 |
-
"assets/assets/config/default.yaml": "
|
| 31 |
-
"assets/assets/config/tikslop.yaml": "
|
| 32 |
"canvaskit/skwasm.js": "ea559890a088fe28b4ddf70e17e60052",
|
| 33 |
"canvaskit/skwasm.js.symbols": "9fe690d47b904d72c7d020bd303adf16",
|
| 34 |
"canvaskit/canvaskit.js.symbols": "27361387bc24144b46a745f1afe92b50",
|
|
|
|
| 3 |
const TEMP = 'flutter-temp-cache';
|
| 4 |
const CACHE_NAME = 'flutter-app-cache';
|
| 5 |
|
| 6 |
+
const RESOURCES = {"flutter_bootstrap.js": "04ff3a8576d911a2f01466a30986bd48",
|
| 7 |
"version.json": "68350cac7987de2728345c72918dd067",
|
| 8 |
"tikslop.png": "570e1db759046e2d224fef729983634e",
|
| 9 |
"index.html": "3a7029b3672560e7938aab6fa4d30a46",
|
| 10 |
"/": "3a7029b3672560e7938aab6fa4d30a46",
|
| 11 |
+
"main.dart.js": "44d4476ea7e6f9159320973c3d29cbc3",
|
| 12 |
"tikslop.svg": "26140ba0d153b213b122bc6ebcc17f6c",
|
| 13 |
"flutter.js": "83d881c1dbb6d6bcd6b42e274605b69c",
|
| 14 |
"favicon.png": "c8a183c516004e648a7bac7497c89b97",
|
|
|
|
| 17 |
"icons/Icon-maskable-512.png": "8682b581a7dab984ef4f9b7f21976a64",
|
| 18 |
"icons/Icon-512.png": "8682b581a7dab984ef4f9b7f21976a64",
|
| 19 |
"manifest.json": "c0904388ddaba6a9bd572a80f79a8dcc",
|
| 20 |
+
"assets/AssetManifest.json": "7c3f24a308a466794e1c04bd7b46567e",
|
| 21 |
"assets/NOTICES": "f0cfae681e209e19b2b144a9f062a96f",
|
| 22 |
"assets/FontManifest.json": "dc3d03800ccca4601324923c0b1d6d57",
|
| 23 |
+
"assets/AssetManifest.bin.json": "b4f8d70a60cc7fe6916c636377e8d4bc",
|
| 24 |
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "33b7d9392238c04c131b6ce224e13711",
|
| 25 |
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
|
| 26 |
+
"assets/AssetManifest.bin": "afdc174fb4cb8a6401bd2328a67e184c",
|
| 27 |
"assets/fonts/MaterialIcons-Regular.otf": "06b86454c633cc9510ad85ddc0523a91",
|
| 28 |
+
"assets/assets/ads/smolagents.gif": "45338af5a4d440b707d02f364be8195c",
|
| 29 |
+
"assets/assets/ads/README.md": "1959fb6b85a966348396f2f0f9c3f32a",
|
| 30 |
+
"assets/assets/ads/lerobot.gif": "0f90b2fc4d15eefb5572363724d6d925",
|
| 31 |
"assets/assets/config/README.md": "07a87720dd00dd1ca98c9d6884440e31",
|
| 32 |
+
"assets/assets/config/custom.yaml": "52bd30aa4d8b980626a5eb02d0871c01",
|
| 33 |
+
"assets/assets/config/default.yaml": "9ca1d05d06721c2b6f6382a1ba40af48",
|
| 34 |
+
"assets/assets/config/tikslop.yaml": "1165218a000aa0c9841e88b072e40756",
|
| 35 |
"canvaskit/skwasm.js": "ea559890a088fe28b4ddf70e17e60052",
|
| 36 |
"canvaskit/skwasm.js.symbols": "9fe690d47b904d72c7d020bd303adf16",
|
| 37 |
"canvaskit/canvaskit.js.symbols": "27361387bc24144b46a745f1afe92b50",
|
build/web/index.html
CHANGED
|
@@ -156,7 +156,7 @@
|
|
| 156 |
</script>
|
| 157 |
|
| 158 |
<!-- Add version parameter for cache busting -->
|
| 159 |
-
<script src="flutter_bootstrap.js?v=
|
| 160 |
|
| 161 |
<!-- Add cache busting script -->
|
| 162 |
<script>
|
|
|
|
| 156 |
</script>
|
| 157 |
|
| 158 |
<!-- Add version parameter for cache busting -->
|
| 159 |
+
<script src="flutter_bootstrap.js?v=1747155709" async></script>
|
| 160 |
|
| 161 |
<!-- Add cache busting script -->
|
| 162 |
<script>
|
build/web/main.dart.js
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
lib/config/config.dart
CHANGED
|
@@ -164,4 +164,23 @@ class Configuration {
|
|
| 164 |
|
| 165 |
Duration get actualClipPlaybackDuration =>
|
| 166 |
actualClipDuration - transitionBufferDuration;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
}
|
|
|
|
| 164 |
|
| 165 |
Duration get actualClipPlaybackDuration =>
|
| 166 |
actualClipDuration - transitionBufferDuration;
|
| 167 |
+
|
| 168 |
+
// Advertising settings
|
| 169 |
+
bool get enableAds =>
|
| 170 |
+
_config['advertising']?['enable_ads'] ?? false;
|
| 171 |
+
|
| 172 |
+
List<Map<String, String>> get adBanners {
|
| 173 |
+
final adsList = _config['advertising']?['ad_banners'] as List<dynamic>?;
|
| 174 |
+
if (adsList == null) return [];
|
| 175 |
+
|
| 176 |
+
return adsList.map<Map<String, String>>((ad) {
|
| 177 |
+
if (ad is Map) {
|
| 178 |
+
return {
|
| 179 |
+
'image': ad['image'].toString(),
|
| 180 |
+
'link': ad['link'].toString(),
|
| 181 |
+
};
|
| 182 |
+
}
|
| 183 |
+
return {};
|
| 184 |
+
}).toList();
|
| 185 |
+
}
|
| 186 |
}
|
lib/screens/home_screen.dart
CHANGED
|
@@ -12,6 +12,7 @@ import 'package:tikslop/services/websocket_api_service.dart';
|
|
| 12 |
import 'package:tikslop/services/settings_service.dart';
|
| 13 |
import 'package:tikslop/widgets/video_card.dart';
|
| 14 |
import 'package:tikslop/widgets/search_box.dart';
|
|
|
|
| 15 |
import 'package:tikslop/theme/colors.dart';
|
| 16 |
|
| 17 |
class HomeScreen extends StatefulWidget {
|
|
@@ -446,17 +447,22 @@ class _HomeScreenState extends State<HomeScreen> {
|
|
| 446 |
// Results Grid
|
| 447 |
Expanded(
|
| 448 |
child: _results.isEmpty
|
| 449 |
-
?
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
),
|
| 458 |
-
|
| 459 |
-
|
|
|
|
| 460 |
)
|
| 461 |
: MasonryGridView.count(
|
| 462 |
padding: const EdgeInsets.all(16),
|
|
|
|
| 12 |
import 'package:tikslop/services/settings_service.dart';
|
| 13 |
import 'package:tikslop/widgets/video_card.dart';
|
| 14 |
import 'package:tikslop/widgets/search_box.dart';
|
| 15 |
+
import 'package:tikslop/widgets/ad_banner.dart';
|
| 16 |
import 'package:tikslop/theme/colors.dart';
|
| 17 |
|
| 18 |
class HomeScreen extends StatefulWidget {
|
|
|
|
| 447 |
// Results Grid
|
| 448 |
Expanded(
|
| 449 |
child: _results.isEmpty
|
| 450 |
+
? Column(
|
| 451 |
+
mainAxisAlignment: MainAxisAlignment.center,
|
| 452 |
+
children: [
|
| 453 |
+
Text(
|
| 454 |
+
_isSearching
|
| 455 |
+
? 'Hallucinating search results using AI...'
|
| 456 |
+
: 'Results are generated on demand, videos rendered on the fly.',
|
| 457 |
+
style: const TextStyle(
|
| 458 |
+
color: TikSlopColors.onSurfaceVariant,
|
| 459 |
+
fontSize: 20
|
| 460 |
+
),
|
| 461 |
+
textAlign: TextAlign.center,
|
| 462 |
),
|
| 463 |
+
if (_isSearching) const SizedBox(height: 16),
|
| 464 |
+
if (_isSearching) const AdBanner(showAd: true),
|
| 465 |
+
],
|
| 466 |
)
|
| 467 |
: MasonryGridView.count(
|
| 468 |
padding: const EdgeInsets.all(16),
|
lib/widgets/ad_banner.dart
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// lib/widgets/ad_banner.dart
|
| 2 |
+
import 'dart:math';
|
| 3 |
+
import 'dart:async';
|
| 4 |
+
import 'package:flutter/material.dart';
|
| 5 |
+
import 'package:flutter/foundation.dart';
|
| 6 |
+
import 'package:tikslop/config/config.dart';
|
| 7 |
+
import 'package:tikslop/theme/colors.dart';
|
| 8 |
+
import 'package:url_launcher/url_launcher.dart';
|
| 9 |
+
import 'package:universal_html/html.dart' if (dart.library.io) 'package:tikslop/services/html_stub.dart' as html;
|
| 10 |
+
|
| 11 |
+
class AdBanner extends StatefulWidget {
|
| 12 |
+
final bool showAd;
|
| 13 |
+
|
| 14 |
+
const AdBanner({
|
| 15 |
+
super.key,
|
| 16 |
+
this.showAd = true,
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
@override
|
| 20 |
+
State<AdBanner> createState() => _AdBannerState();
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
class _AdBannerState extends State<AdBanner> {
|
| 24 |
+
Map<String, String>? _currentAd;
|
| 25 |
+
Timer? _rotationTimer;
|
| 26 |
+
|
| 27 |
+
@override
|
| 28 |
+
void initState() {
|
| 29 |
+
super.initState();
|
| 30 |
+
// Initialize with a random ad
|
| 31 |
+
_selectRandomAd();
|
| 32 |
+
// Start the rotation timer
|
| 33 |
+
_startRotationTimer();
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
@override
|
| 37 |
+
void dispose() {
|
| 38 |
+
// Cancel the timer when the widget is disposed
|
| 39 |
+
_rotationTimer?.cancel();
|
| 40 |
+
super.dispose();
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
/// Starts the ad rotation timer
|
| 44 |
+
void _startRotationTimer() {
|
| 45 |
+
// Rotate every 30 seconds
|
| 46 |
+
_rotationTimer = Timer.periodic(const Duration(seconds: 30), (timer) {
|
| 47 |
+
_selectRandomAd();
|
| 48 |
+
});
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
/// Selects a new random ad and updates the state
|
| 52 |
+
void _selectRandomAd() {
|
| 53 |
+
if (!mounted) return;
|
| 54 |
+
|
| 55 |
+
final ads = Configuration.instance.adBanners;
|
| 56 |
+
if (ads.isEmpty) {
|
| 57 |
+
setState(() => _currentAd = null);
|
| 58 |
+
return;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
final random = Random();
|
| 62 |
+
setState(() => _currentAd = ads[random.nextInt(ads.length)]);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
/// Opens a URL in a new tab or browser
|
| 66 |
+
Future<void> _launchURL(String url) async {
|
| 67 |
+
final Uri uri = Uri.parse(url);
|
| 68 |
+
if (kIsWeb) {
|
| 69 |
+
// Use HTML for web platform
|
| 70 |
+
html.window.open(url, '_blank');
|
| 71 |
+
} else {
|
| 72 |
+
// Use url_launcher for other platforms
|
| 73 |
+
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
| 74 |
+
throw Exception('Could not launch $url');
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
@override
|
| 80 |
+
Widget build(BuildContext context) {
|
| 81 |
+
// Only show ads if enabled in config and showAd is true
|
| 82 |
+
if (!Configuration.instance.enableAds || !widget.showAd) {
|
| 83 |
+
return const SizedBox.shrink();
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
if (_currentAd == null || _currentAd!.isEmpty) {
|
| 87 |
+
return const SizedBox.shrink();
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
return Column(
|
| 91 |
+
mainAxisSize: MainAxisSize.min,
|
| 92 |
+
children: [
|
| 93 |
+
// Divider above ad
|
| 94 |
+
const Divider(color: TikSlopColors.surfaceVariant),
|
| 95 |
+
|
| 96 |
+
// Ad banner
|
| 97 |
+
Padding(
|
| 98 |
+
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
| 99 |
+
child: InkWell(
|
| 100 |
+
onTap: () => _launchURL(_currentAd!['link'] ?? ''),
|
| 101 |
+
child: Image.asset(
|
| 102 |
+
_currentAd!['image'] ?? '',
|
| 103 |
+
height: 64,
|
| 104 |
+
fit: BoxFit.contain,
|
| 105 |
+
errorBuilder: (context, error, stackTrace) {
|
| 106 |
+
// If image fails to load, show a placeholder
|
| 107 |
+
print('Error loading ad image: $error');
|
| 108 |
+
return Container(
|
| 109 |
+
height: 64,
|
| 110 |
+
color: Colors.grey.withOpacity(0.1),
|
| 111 |
+
child: const Center(child: Text('Ad')),
|
| 112 |
+
);
|
| 113 |
+
},
|
| 114 |
+
),
|
| 115 |
+
),
|
| 116 |
+
),
|
| 117 |
+
],
|
| 118 |
+
);
|
| 119 |
+
}
|
| 120 |
+
}
|
pubspec.yaml
CHANGED
|
@@ -79,6 +79,7 @@ flutter:
|
|
| 79 |
# To add assets to your application, add an assets section, like this:
|
| 80 |
assets:
|
| 81 |
- assets/config/
|
|
|
|
| 82 |
|
| 83 |
# An image asset can refer to one or more resolution-specific "variants", see
|
| 84 |
# https://flutter.dev/to/resolution-aware-images
|
|
|
|
| 79 |
# To add assets to your application, add an assets section, like this:
|
| 80 |
assets:
|
| 81 |
- assets/config/
|
| 82 |
+
- assets/ads/
|
| 83 |
|
| 84 |
# An image asset can refer to one or more resolution-specific "variants", see
|
| 85 |
# https://flutter.dev/to/resolution-aware-images
|