Clean TV navigation traces and update app icons

This commit is contained in:
dwindown
2026-03-31 14:18:09 +07:00
parent 8774735e38
commit 49f130b5ea
33 changed files with 58 additions and 26 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -10,6 +10,7 @@ import '../../core/sacred_tokens.dart';
import '../../providers.dart'; import '../../providers.dart';
import '../../data/services/sync_service.dart'; import '../../data/services/sync_service.dart';
import '../../data/services/myquran_service.dart'; import '../../data/services/myquran_service.dart';
import '../../data/services/sound_service.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'dart:io'; import 'dart:io';
@@ -120,7 +121,7 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
_simulasiFocusNodes = [ _simulasiFocusNodes = [
_simulasiEntryFocusNode, _simulasiEntryFocusNode,
...List.generate( ...List.generate(
6, 8,
(index) => FocusNode(debugLabel: 'simulasi_row_${index + 1}'), (index) => FocusNode(debugLabel: 'simulasi_row_${index + 1}'),
), ),
]; ];
@@ -1005,16 +1006,8 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
setState(() => _selectedTab = index); setState(() => _selectedTab = index);
} }
void _traceNav(String message) {
assert(() {
debugPrint('[TV NAV] $message');
return true;
}());
}
void _focusNavTab(int index) { void _focusNavTab(int index) {
if (index < 0 || index >= _navFocusNodes.length) return; if (index < 0 || index >= _navFocusNodes.length) return;
_traceNav('focus nav[$index]');
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) { if (mounted) {
_navFocusNodes[index].requestFocus(); _navFocusNodes[index].requestFocus();
@@ -1025,7 +1018,6 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
void _focusIdentityRow(int index) { void _focusIdentityRow(int index) {
if (_selectedTab != 0) return; if (_selectedTab != 0) return;
if (index < 0 || index >= _identityFocusNodes.length) return; if (index < 0 || index >= _identityFocusNodes.length) return;
_traceNav('focus identitas[$index]');
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) { if (mounted) {
_identityFocusNodes[index].requestFocus(); _identityFocusNodes[index].requestFocus();
@@ -1036,7 +1028,6 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
void _focusJumatRow(int index) { void _focusJumatRow(int index) {
if (_selectedTab != 3) return; if (_selectedTab != 3) return;
if (index < 0 || index >= _jumatFocusNodes.length) return; if (index < 0 || index >= _jumatFocusNodes.length) return;
_traceNav('focus jumat[$index]');
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) { if (mounted) {
_jumatFocusNodes[index].requestFocus(); _jumatFocusNodes[index].requestFocus();
@@ -1047,7 +1038,6 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
void _focusSimulasiRow(int index) { void _focusSimulasiRow(int index) {
if (_selectedTab != 4) return; if (_selectedTab != 4) return;
if (index < 0 || index >= _simulasiFocusNodes.length) return; if (index < 0 || index >= _simulasiFocusNodes.length) return;
_traceNav('focus simulasi[$index]');
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) { if (mounted) {
_simulasiFocusNodes[index].requestFocus(); _simulasiFocusNodes[index].requestFocus();
@@ -1210,7 +1200,6 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
return KeyEventResult.ignored; return KeyEventResult.ignored;
} }
final key = event.logicalKey; final key = event.logicalKey;
_traceNav('identitas[$index] key=$key');
if (key == LogicalKeyboardKey.arrowUp) { if (key == LogicalKeyboardKey.arrowUp) {
_focusIdentityRow(index - 1); _focusIdentityRow(index - 1);
return KeyEventResult.handled; return KeyEventResult.handled;
@@ -1274,7 +1263,6 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
return KeyEventResult.ignored; return KeyEventResult.ignored;
} }
final key = event.logicalKey; final key = event.logicalKey;
_traceNav('simulasi[$index] key=$key');
if (key == LogicalKeyboardKey.arrowUp) { if (key == LogicalKeyboardKey.arrowUp) {
_focusSimulasiRow(index - 1); _focusSimulasiRow(index - 1);
return KeyEventResult.handled; return KeyEventResult.handled;
@@ -3393,6 +3381,18 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
rowIndex: 0, rowIndex: 0,
), ),
SizedBox(height: 16 * s), SizedBox(height: 16 * s),
_simulasiCard(
s: s,
title: '15 Detik Sebelum Adzan',
icon: HugeIcons.strokeRoundedNotification03,
desc: 'Melompat ke 15 detik sebelum Adzan Dzuhur untuk memeriksa transisi terakhir menuju Adzan.',
onTap: () => _activateSimulation(
() => _simulateEvent('pre_adzan_15'),
),
focusNode: _simulasiFocusNodes[1],
rowIndex: 1,
),
SizedBox(height: 16 * s),
_simulasiCard( _simulasiCard(
s: s, s: s,
title: 'Menuju Adzan', title: 'Menuju Adzan',
@@ -3401,8 +3401,8 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
onTap: () => _activateSimulation( onTap: () => _activateSimulation(
() => _simulateEvent('pre_adzan'), () => _simulateEvent('pre_adzan'),
), ),
focusNode: _simulasiFocusNodes[1], focusNode: _simulasiFocusNodes[2],
rowIndex: 1, rowIndex: 2,
), ),
SizedBox(height: 16 * s), SizedBox(height: 16 * s),
_simulasiCard( _simulasiCard(
@@ -3413,8 +3413,20 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
onTap: () => _activateSimulation( onTap: () => _activateSimulation(
() => _simulateEvent('adzan'), () => _simulateEvent('adzan'),
), ),
focusNode: _simulasiFocusNodes[2], focusNode: _simulasiFocusNodes[3],
rowIndex: 2, rowIndex: 3,
),
SizedBox(height: 16 * s),
_simulasiCard(
s: s,
title: '15 Detik Sebelum Iqamah',
icon: HugeIcons.strokeRoundedTimer02,
desc: 'Melompat ke 15 detik sebelum Iqamah Dzuhur untuk memeriksa hitungan mundur terakhir.',
onTap: () => _activateSimulation(
() => _simulateEvent('pre_iqomah_15'),
),
focusNode: _simulasiFocusNodes[4],
rowIndex: 4,
), ),
SizedBox(height: 16 * s), SizedBox(height: 16 * s),
_simulasiCard( _simulasiCard(
@@ -3425,8 +3437,8 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
onTap: () => _activateSimulation( onTap: () => _activateSimulation(
() => _simulateEvent('iqomah'), () => _simulateEvent('iqomah'),
), ),
focusNode: _simulasiFocusNodes[3], focusNode: _simulasiFocusNodes[5],
rowIndex: 3, rowIndex: 5,
), ),
SizedBox(height: 16 * s), SizedBox(height: 16 * s),
_simulasiCard( _simulasiCard(
@@ -3437,8 +3449,8 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
onTap: () => _activateSimulation( onTap: () => _activateSimulation(
() => _simulateEvent('jumat_incoming'), () => _simulateEvent('jumat_incoming'),
), ),
focusNode: _simulasiFocusNodes[4], focusNode: _simulasiFocusNodes[6],
rowIndex: 4, rowIndex: 6,
), ),
SizedBox(height: 16 * s), SizedBox(height: 16 * s),
_simulasiCard( _simulasiCard(
@@ -3449,8 +3461,8 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
onTap: () => _activateSimulation( onTap: () => _activateSimulation(
() => _simulateEvent('jumat_khutbah'), () => _simulateEvent('jumat_khutbah'),
), ),
focusNode: _simulasiFocusNodes[5], focusNode: _simulasiFocusNodes[7],
rowIndex: 5, rowIndex: 7,
), ),
SizedBox(height: 16 * s), SizedBox(height: 16 * s),
_simulasiCard( _simulasiCard(
@@ -3461,8 +3473,8 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
onTap: () => _activateSimulation( onTap: () => _activateSimulation(
() => _simulateEvent('shalat'), () => _simulateEvent('shalat'),
), ),
focusNode: _simulasiFocusNodes[6], focusNode: _simulasiFocusNodes[8],
rowIndex: 6, rowIndex: 8,
), ),
], ],
), ),
@@ -3598,12 +3610,21 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
DateTime targetTime; DateTime targetTime;
switch (eventType) { switch (eventType) {
case 'pre_adzan_15':
targetTime = dzuhurTime.subtract(const Duration(seconds: 15));
break;
case 'pre_adzan': case 'pre_adzan':
targetTime = dzuhurTime.subtract(const Duration(minutes: 2)); targetTime = dzuhurTime.subtract(const Duration(minutes: 2));
break; break;
case 'adzan': case 'adzan':
targetTime = dzuhurTime; targetTime = dzuhurTime;
break; break;
case 'pre_iqomah_15':
final settings = ref.read(settingsProvider);
targetTime = dzuhurTime
.add(Duration(minutes: settings.iqomahDzuhur))
.subtract(const Duration(seconds: 15));
break;
case 'iqomah': case 'iqomah':
targetTime = dzuhurTime.add(const Duration(seconds: 45)); // During iqomah targetTime = dzuhurTime.add(const Duration(seconds: 45)); // During iqomah
break; break;
@@ -3630,6 +3651,17 @@ class _AdminScreenState extends ConsumerState<AdminScreen> {
final offset = targetTime.difference(realNow); final offset = targetTime.difference(realNow);
_simulateTimeOffset(offset); _simulateTimeOffset(offset);
switch (eventType) {
case 'adzan':
unawaited(SoundService.instance.playAdzanBeep());
break;
case 'iqomah':
unawaited(SoundService.instance.playIqomahCountdown());
break;
default:
break;
}
} }
void _activateSimulation(VoidCallback action) { void _activateSimulation(VoidCallback action) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 917 B

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB