Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
160 commits
Select commit Hold shift + click to select a range
1ee10c7
refactor(cleanup): remove unused `_swatch` from `FLauncherApp`
LeanBitLab May 17, 2026
65b9b42
Merge pull request #80 from LeanBitLab/cleanup-unused-swatch-10803040…
LeanBitLab May 17, 2026
8a33836
test(models): add unit tests for Category model
LeanBitLab May 17, 2026
988ec40
Merge pull request #81 from LeanBitLab/add-category-tests-16392016201…
LeanBitLab May 17, 2026
84d594b
test: add unit tests for LauncherState.toggleLauncherVisibility
LeanBitLab May 17, 2026
8f704c2
Merge pull request #82 from LeanBitLab/test-launcher-state-toggle-167…
LeanBitLab May 17, 2026
d58b59a
test: remove unused variables in app_card_test.dart
LeanBitLab May 24, 2026
412e4ff
Merge pull request #85 from LeanBitLab/fix/app-card-test-unused-varia…
LeanBitLab May 24, 2026
0dbe120
Add accessibility settings page, clean up gitignore for IzzyOnDroid b…
LeanBitLab May 27, 2026
b8b4329
Gitignore dev tooling files not needed for builds
LeanBitLab May 27, 2026
497d707
Update AGENTS.md with legacy package, gitignore policy, migration saf…
LeanBitLab May 27, 2026
ac0a6d9
Revert "Update AGENTS.md with legacy package, gitignore policy, migra…
LeanBitLab May 27, 2026
763178c
feat: add tv input selector and optimize apk size
LeanBitLab May 28, 2026
bf7fb78
feat: add toggle option for status bar inputs widget
LeanBitLab Jun 1, 2026
9fa5639
feat: add system-wide notification overlay popups
LeanBitLab Jun 1, 2026
b5abe5c
docs: add premium downloader badge to readme
LeanBitLab Jun 1, 2026
9b7bad6
docs: update downloader badge to display code 7259827
LeanBitLab Jun 1, 2026
4b32a3d
chore: update changelog for 8103 with notification popup features
LeanBitLab Jun 1, 2026
9304204
fix: resolve java compilation errors in MainActivity
LeanBitLab Jun 1, 2026
564078a
fix: restore missing imports in LauncherNotificationListenerService
LeanBitLab Jun 1, 2026
99bd53e
fix: resolve test failures - sqlite3 symlink, missing mocks, batch te…
LeanBitLab Jun 1, 2026
84169a9
ci: auto-update test and coverage badges
LeanBitLab Jun 3, 2026
00e5e8e
ci: generate version, download, and star badges
LeanBitLab Jun 3, 2026
c4136d4
ci: use local version, download, and star badges in README
LeanBitLab Jun 3, 2026
1f2b45c
ci: fix python indentation in workflow
LeanBitLab Jun 3, 2026
782a62b
ci: use textwrap to fix yaml syntax error
LeanBitLab Jun 3, 2026
141c5fe
ci: fix python indentation for all script blocks
LeanBitLab Jun 3, 2026
dd00fc2
ci: use cat and sed to format python scripts
LeanBitLab Jun 3, 2026
3dd121c
ci: add script debug prints to workflow
LeanBitLab Jun 3, 2026
a813520
ci: extract script logic to separate files
LeanBitLab Jun 3, 2026
3329455
chore: auto-update badges
LeanBitLab Jun 3, 2026
1f7ae2e
ci: generate drift schemas in workflow
LeanBitLab Jun 3, 2026
29692df
ci: add database schema snapshots for tests
LeanBitLab Jun 3, 2026
c6a8ccd
chore: auto-update badges
LeanBitLab Jun 3, 2026
3043644
ci: run badges workflow weekly
LeanBitLab Jun 3, 2026
5af9d97
ci: separate stats badges to daily workflow
LeanBitLab Jun 3, 2026
2628c47
ci: add universal-only build flag to gradle
LeanBitLab Jun 3, 2026
a941a8f
ci: add pre-release badge to readme
LeanBitLab Jun 3, 2026
b4ec861
chore: auto-update stats badges
LeanBitLab Jun 3, 2026
3721333
ci: update pre-release badge to flat style
LeanBitLab Jun 3, 2026
f2378aa
ci: force bypass github camo cache for pre-release badge
LeanBitLab Jun 3, 2026
78c880f
ci: replace svg badge with custom rounded png button
LeanBitLab Jun 3, 2026
e8ea9b9
ci: remove version from pre-release badge
LeanBitLab Jun 3, 2026
66ddde4
docs: remove version from pre-release badge alt text
LeanBitLab Jun 3, 2026
c45f94e
docs: increase download badges height to 65px
LeanBitLab Jun 3, 2026
cccdc92
docs: crop padding from github and izzyondroid badges to match sizes
LeanBitLab Jun 3, 2026
e0e782e
docs: use relative paths for download button images to prevent broken…
LeanBitLab Jun 3, 2026
7dd65fa
design: theme match downloader code badge image
LeanBitLab Jun 3, 2026
aaa885d
chore: auto-update stats badges
LeanBitLab Jun 4, 2026
5a1973d
chore: auto-update stats badges
LeanBitLab Jun 5, 2026
aec1ab9
chore: auto-update stats badges
LeanBitLab Jun 6, 2026
191ea48
chore: auto-update stats badges
LeanBitLab Jun 7, 2026
9846793
chore: auto-update stats badges
LeanBitLab Jun 8, 2026
e1d9d59
chore: auto-update stats badges
LeanBitLab Jun 9, 2026
cfe6652
chore: auto-update stats badges
LeanBitLab Jun 10, 2026
47cb33f
chore: auto-update stats badges
LeanBitLab Jun 11, 2026
e4dea6a
chore: auto-update stats badges
LeanBitLab Jun 12, 2026
8517a44
chore: auto-update stats badges
LeanBitLab Jun 13, 2026
2c01961
chore: auto-update stats badges
LeanBitLab Jun 14, 2026
8b61688
chore: auto-update stats badges
LeanBitLab Jun 15, 2026
986ac5a
chore: auto-update stats badges
LeanBitLab Jun 16, 2026
99f2e2b
chore: auto-update stats badges
LeanBitLab Jun 17, 2026
5e22776
chore: auto-update stats badges
LeanBitLab Jun 18, 2026
e216685
chore: auto-update stats badges
LeanBitLab Jun 19, 2026
c1ba4a8
chore: auto-update stats badges
LeanBitLab Jun 20, 2026
a0b2d9b
refactor(settings): use trailing widget for status
LeanBitLab Jun 13, 2026
93b0535
chore: improve and consolidate gitignore rules
LeanBitLab Jun 20, 2026
87030f5
chore: auto-update stats badges
LeanBitLab Jun 20, 2026
dfebd2d
chore: auto-update stats badges
LeanBitLab Jun 21, 2026
8c29b46
fix(network): refresh permission state when app resumes
LeanBitLab Jun 20, 2026
4fefd88
feat(notifications): add dismissal & bell drawer
LeanBitLab Jun 20, 2026
67aa9dc
feat(watch-next): add continue watching support
LeanBitLab Jun 20, 2026
1c14918
feat(notifications): add settings toggle for status bar notification …
LeanBitLab Jun 20, 2026
dece1b7
feat(notifications): add custom focus border for dismissal and add a …
LeanBitLab Jun 20, 2026
23641ed
chore(release): update fastlane changelog for version 8103 with recen…
LeanBitLab Jun 20, 2026
a93ae41
feat(notifications): remove bottom clear all and close buttons, and i…
LeanBitLab Jun 20, 2026
4bc242f
feat(accessibility): implement built-in LauncherAccessibilityService …
LeanBitLab Jun 20, 2026
8f9e816
fix(notifications): filter out media playback ongoing events and gene…
LeanBitLab Jun 20, 2026
fdc209a
chore(accessibility): rename Home Button Hijack to Home Button Fix
LeanBitLab Jun 20, 2026
e5b2940
feat(backup): support multiple backups with visual list picker
LeanBitLab Jun 21, 2026
737585e
chore: auto-update test and coverage badges
LeanBitLab Jun 21, 2026
37eb8c0
docs: update README with latest features
LeanBitLab Jun 21, 2026
78b080c
docs: update README with native default launcher configuration instru…
LeanBitLab Jun 21, 2026
0b7666f
docs: document built-in Home Button Fix accessibility remapper in README
LeanBitLab Jun 21, 2026
9cfb9b4
feat: fix permission settings and share backups
LeanBitLab Jun 21, 2026
bf3f8bc
fix continue watching layout, permissions, focus scroll
LeanBitLab Jun 21, 2026
04c4bc3
chore: auto-update stats badges
LeanBitLab Jun 21, 2026
af36dbc
chore: auto-update stats badges
LeanBitLab Jun 22, 2026
aacb6c9
chore: auto-update stats badges
LeanBitLab Jun 23, 2026
1796722
Update app_es.arb
wuniversales Jun 23, 2026
1d42279
Merge pull request #98 from wuniversales/patch-1
LeanBitLab Jun 23, 2026
4a36f64
chore: auto-update stats badges
LeanBitLab Jun 23, 2026
107c7c8
fix: key sound, custom reorder, vpn detection, and badge push conflict
LeanBitLab Jun 23, 2026
c60162b
chore: auto-update badges
LeanBitLab Jun 23, 2026
d2163b8
fix: open vpn settings on vpn icon click
LeanBitLab Jun 23, 2026
764ffd1
chore: add version 8104 changelog
LeanBitLab Jun 23, 2026
2880efa
chore: auto-update badges
LeanBitLab Jun 23, 2026
87526ba
ci: pull and rebase before pushing badges
LeanBitLab Jun 23, 2026
0deb572
chore: auto-update badges
LeanBitLab Jun 23, 2026
67529b8
feat: auto-hide empty notification bell
LeanBitLab Jun 23, 2026
4925ed3
chore: auto-update badges
LeanBitLab Jun 23, 2026
976b3c4
chore: auto-update badges
LeanBitLab Jun 24, 2026
399f394
chore: auto-update badges
LeanBitLab Jun 25, 2026
062461e
chore: auto-update badges
LeanBitLab Jun 26, 2026
c39877a
chore: auto-update badges
LeanBitLab Jun 27, 2026
8bcfefa
chore: auto-update badges
LeanBitLab Jun 28, 2026
4ae25f4
chore: auto-update badges
LeanBitLab Jun 29, 2026
89d454d
chore: auto-update badges
LeanBitLab Jun 30, 2026
d6a2fcf
chore: auto-update badges
LeanBitLab Jul 1, 2026
3594523
chore: auto-update badges
LeanBitLab Jul 2, 2026
ca6ec7a
chore: auto-update badges
LeanBitLab Jul 3, 2026
8eba2a4
⚡ Improve Backup Restore Performance with Batch Inserts
LeanBitLab Jul 3, 2026
bc5c44b
Merge pull request #101 from LeanBitLab/jules-6675736721813348581-9a7…
LeanBitLab Jul 3, 2026
d8ff0ad
chore: auto-update badges
LeanBitLab Jul 3, 2026
809430f
chore: auto-update badges
LeanBitLab Jul 5, 2026
8a4f0a9
chore: auto-update badges
LeanBitLab Jul 6, 2026
1fe602e
chore: auto-update badges
LeanBitLab Jul 7, 2026
fca2cb6
chore: auto-update badges
LeanBitLab Jul 8, 2026
315919f
chore: auto-update badges
LeanBitLab Jul 9, 2026
ac84772
fix: resolve app reordering race on fast input
LeanBitLab Jul 9, 2026
32b57eb
docs: move screenshots section before features in readme
LeanBitLab Jul 9, 2026
f18009c
docs: temporarily hide pre-release button in readme
LeanBitLab Jul 9, 2026
91d72df
chore: auto-update badges
LeanBitLab Jul 9, 2026
a4df375
fix: resolve categoryOrders missing for hidden apps on start
LeanBitLab Jul 9, 2026
24bf456
fix: support goBack and gameButtonB to exit reorder mode
LeanBitLab Jul 9, 2026
c44c745
test: add widget test for reorder cancels on Back button
LeanBitLab Jul 9, 2026
0a8bc87
style: force notification badge count text color to white
LeanBitLab Jul 9, 2026
1315c64
chore: auto-update badges
LeanBitLab Jul 9, 2026
4eb1567
ci: trigger update-badges workflow only daily and manually
LeanBitLab Jul 9, 2026
5230506
ci: add release-apk workflow for building and publishing release APK
LeanBitLab Jul 9, 2026
7e4c871
ci: configure release-apk to generate dynamic release notes and build…
LeanBitLab Jul 9, 2026
fc4562f
chore: bump version to 2026.07.10+8105 and add fastlane changelog
LeanBitLab Jul 9, 2026
41cf546
ci: support HEAD fallback for tag description in release note generation
LeanBitLab Jul 9, 2026
b58746e
ci: update release note generation to fetch changelog from Fastlane f…
LeanBitLab Jul 9, 2026
3fe492e
ci: fix base64 decode crash by adding ignore-garbage flag
LeanBitLab Jul 9, 2026
578ff16
ci: use python base64 decoding for release key
LeanBitLab Jul 9, 2026
f348051
ci: use direct secrets expansion to fix multiline base64 decode crash
LeanBitLab Jul 9, 2026
9a52b79
ci: fix secrets context access in step if condition
LeanBitLab Jul 9, 2026
12da7ea
ci: use python base64 sanitizer to decode keystore
LeanBitLab Jul 9, 2026
8aa6652
ci: use Java 21 for release build
LeanBitLab Jul 9, 2026
c3d0bea
ci: pass release credentials via env variables instead of local.prope…
LeanBitLab Jul 9, 2026
7fbbc76
workflow: dynamic prerelease by tag name
LeanBitLab Jul 10, 2026
21337fc
workflow: fix split build target platforms
LeanBitLab Jul 10, 2026
64b0f7b
doc: show pre-release button in README
LeanBitLab Jul 10, 2026
d138dfc
workflow: rename release APKs to LTvLauncher-*
LeanBitLab Jul 10, 2026
211004b
fix: watch later functional and visual bugs, add test mock mode
LeanBitLab Jul 10, 2026
d58ed20
build: override split APK versionCode to keep base value
LeanBitLab Jul 10, 2026
484bbc0
style: update release notes artifacts format
LeanBitLab Jul 10, 2026
2b3f9be
style: fix formatting in release notes script
LeanBitLab Jul 10, 2026
735b8da
chore: auto-update badges
LeanBitLab Jul 11, 2026
37464e5
chore: auto-update badges
LeanBitLab Jul 12, 2026
248fed4
chore: make release signing config conditional
LeanBitLab Jul 12, 2026
b1c5ef1
feat: add spanish translations for continue watching
LeanBitLab Jul 12, 2026
f6b3e43
fix: resolve back button in reorder mode and sections scrolling
LeanBitLab Jul 12, 2026
916fac8
fix: resolve race condition and duplicates in rapid app reordering
LeanBitLab Jul 12, 2026
018b80f
fix: support package usage stats default appops mode
LeanBitLab Jul 12, 2026
a1d723c
feat: render both physical network and VPN status icons
LeanBitLab Jul 12, 2026
0812a21
fix: define KEY_VPN_ACTIVE constant
LeanBitLab Jul 12, 2026
489c676
bump: version 2026.07.12+8106 and add changelog
LeanBitLab Jul 12, 2026
e6ae2bd
fix: resolve import backup silently failing due to deactivated widget…
ivanwongtf Jul 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .github/assets/IzzyOnDroid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
Binary file added .github/assets/get_it_on_downloader.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/assets/get_it_on_github.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions .github/badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions .github/badges/downloads.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/badges/prerelease.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions .github/badges/stars.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions .github/badges/tests.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions .github/badges/version.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions .github/scripts/calculate_coverage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import os

if os.path.exists('coverage/lcov.info'):
lf = 0
lh = 0
with open('coverage/lcov.info') as f:
for line in f:
if line.startswith('LF:'):
lf += int(line.split(':')[1])
elif line.startswith('LH:'):
lh += int(line.split(':')[1])
percentage = (lh / lf) * 100 if lf > 0 else 0.0
else:
percentage = 0.0

percentage_str = f"{percentage:.1f}"

# Color logic
if percentage >= 90:
color = 'green'
elif percentage >= 75:
color = 'yellowgreen'
elif percentage >= 50:
color = 'yellow'
else:
color = 'red'

github_output = os.environ.get('GITHUB_OUTPUT')
if github_output:
with open(github_output, 'a') as f:
f.write(f'percent={percentage_str}\n')
f.write(f'color={color}\n')
36 changes: 36 additions & 0 deletions .github/scripts/calculate_test_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import json
import os

if os.path.exists('test-reports/results.json'):
success = 0
failed = 0
with open('test-reports/results.json') as f:
for line in f:
try:
data = json.loads(line)
if data.get('type') == 'testDone':
if data.get('hidden', False):
continue
res = data.get('result')
if res == 'success':
success += 1
elif res in ('failure', 'error'):
failed += 1
except Exception:
pass
total = success + failed
if failed > 0:
summary = f'{success}/{total} passed'
color = 'red'
else:
summary = f'{success} passed'
color = 'green'
else:
summary = 'no tests'
color = 'grey'

github_output = os.environ.get('GITHUB_OUTPUT')
if github_output:
with open(github_output, 'a') as f:
f.write(f'summary={summary}\n')
f.write(f'color={color}\n')
47 changes: 47 additions & 0 deletions .github/scripts/fetch_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import urllib.request
import json
import os

headers = {'User-Agent': 'Mozilla/5.0'}

# Fetch Stars
try:
req_repo = urllib.request.Request('https://api.github.com/repos/LeanBitLab/LtvLauncher', headers=headers)
with urllib.request.urlopen(req_repo) as response:
repo_data = json.loads(response.read().decode())
stars = repo_data.get('stargazers_count', 0)
except Exception as e:
print(f'Error fetching stars: {e}')
stars = 0

# Fetch Releases & Downloads
try:
req_releases = urllib.request.Request('https://api.github.com/repos/LeanBitLab/LtvLauncher/releases', headers=headers)
with urllib.request.urlopen(req_releases) as response:
releases_data = json.loads(response.read().decode())
version = releases_data[0].get('tag_name', 'unknown') if releases_data else 'unknown'
downloads = 0
for release in releases_data:
for asset in release.get('assets', []):
downloads += asset.get('download_count', 0)
except Exception as e:
print(f'Error fetching releases: {e}')
version = 'unknown'
downloads = 0

def format_num(n):
if n >= 1000000:
return f'{n/1000000:.1f}M'
if n >= 1000:
return f'{n/1000:.1f}k'
return str(n)

stars_str = format_num(stars)
downloads_str = format_num(downloads)

github_output = os.environ.get('GITHUB_OUTPUT')
if github_output:
with open(github_output, 'a') as f:
f.write(f'stars={stars_str}\n')
f.write(f'version={version}\n')
f.write(f'downloads={downloads_str}\n')
117 changes: 117 additions & 0 deletions .github/scripts/generate_release_notes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import os
import subprocess

def get_version_code():
try:
with open("pubspec.yaml", "r") as f:
for line in f:
if line.strip().startswith("version:"):
parts = line.strip().split(":")
version_str = parts[1].strip()
if "+" in version_str:
return version_str.split("+")[1].strip()
except Exception:
pass
return None

def get_fastlane_changelog(version_code):
if not version_code:
return None
changelog_path = f"fastlane/metadata/android/en-US/changelogs/{version_code}.txt"
if os.path.exists(changelog_path):
try:
with open(changelog_path, "r") as f:
return f.read().strip()
except Exception:
pass
return None

def get_git_changelog(current_tag):
# Check if the tag exists in git
tag_exists = False
try:
subprocess.check_call(['git', 'rev-parse', current_tag], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
tag_exists = True
except Exception:
tag_exists = False

# If tag exists, compare. If not, use HEAD as current commit.
current_ref = current_tag if tag_exists else "HEAD"

try:
# Find the previous tag before the current tag
prev_tag = subprocess.check_output(
['git', 'describe', '--tags', '--abbrev=0', f'{current_ref}^'],
stderr=subprocess.DEVNULL
).decode().strip()
except Exception:
prev_tag = ""

if prev_tag:
git_log_range = f"{prev_tag}..{current_ref}"
else:
git_log_range = current_ref

try:
log_output = subprocess.check_output(
['git', 'log', '--pretty=format:- %s', git_log_range]
).decode().strip()

changelog_lines = []
if log_output:
for line in log_output.split('\n'):
# Exclude merge commits or chore commits
if "Merge" in line or "chore: " in line:
continue
changelog_lines.append(line)
return "\n".join(changelog_lines) if changelog_lines else "- General improvements and bug fixes"
except Exception as e:
return f"- New changes in release {current_tag}"

def get_file_size(path):
if os.path.exists(path):
size_bytes = os.path.getsize(path)
return f"{size_bytes / (1024 * 1024):.1f} MB"
return "0.0 MB"

def main():
tag_name = os.environ.get('TAG_NAME', '')
if not tag_name:
try:
tag_name = subprocess.check_output(
['git', 'describe', '--tags', '--always']
).decode().strip()
except Exception:
tag_name = "v-dev"

# Try loading Fastlane changelog first
version_code = get_version_code()
changelog = get_fastlane_changelog(version_code)

# Fallback to git changelog if Fastlane is missing/empty
if not changelog:
changelog = get_git_changelog(tag_name)

size_universal = get_file_size("build/app/outputs/flutter-apk/app-release.apk")
size_armv7 = get_file_size("build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk")
size_arm64 = get_file_size("build/app/outputs/flutter-apk/app-arm64-v8a-release.apk")

release_notes = f"""### ❤️ Support the Project
If you love using LTvLauncher (ad-free, lightweight, and open source), please consider supporting us! Your contributions help buy testing hardware, cover bills, and keep development active.
👉 **[Sponsor LeanBitLab on GitHub](https://github.com/sponsors/LeanBitLab)**

### Whats New
{changelog}

#### 📦 Artifacts
* **LTvLauncher-universal-release.apk**: Universal build containing all architectures.
* **LTvLauncher-armeabi-v7a-release.apk**: Optimized build for ARMv7 architectures (older Android TVs & Fire TV sticks).
* **LTvLauncher-arm64-v8a-release.apk**: Optimized build for ARM64 architectures (newer Android TVs & NVIDIA Shield).
"""

with open("release_notes.md", "w") as f:
f.write(release_notes)
print("Successfully generated release_notes.md")

if __name__ == "__main__":
main()
Loading