diff --git a/analysis_options.yaml b/analysis_options.yaml index 0d29021..bf8d421 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -7,6 +7,15 @@ # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** include: package:flutter_lints/flutter.yaml linter: diff --git a/lib/frontend/screens/chats/chat_list_screen.dart b/lib/frontend/screens/chats/chat_list_screen.dart index 5913abb..3f7a15c 100644 --- a/lib/frontend/screens/chats/chat_list_screen.dart +++ b/lib/frontend/screens/chats/chat_list_screen.dart @@ -612,7 +612,8 @@ class _ChatListScreenState extends State _shimmerController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1500), - )..repeat(); + ); + _syncShimmer(); _storiesRevealController = AnimationController( @@ -631,6 +632,7 @@ class _ChatListScreenState extends State setState(() { _sessionState = state; }); + _syncShimmer(); if (state == SessionState.online) { _requestReload(); _maybeLoadStories(); @@ -836,6 +838,7 @@ class _ChatListScreenState extends State _foldersListKnown = null; _isInitialLoading = false; }); + _syncShimmer(); } return; } @@ -928,6 +931,7 @@ class _ChatListScreenState extends State } _isInitialLoading = false; }); + _syncShimmer(); _prefetchContactsForChats(loadedChats); if (widget.archiveMode) { if (filteredChats.isNotEmpty) { @@ -953,6 +957,7 @@ class _ChatListScreenState extends State _foldersListKnown = null; _isInitialLoading = false; }); + _syncShimmer(); } } finally { if (mounted) { @@ -970,6 +975,16 @@ class _ChatListScreenState extends State return _sessionState != SessionState.disconnected; } + void _syncShimmer() { + final needed = _isInitialLoading || _showFoldersShimmer; + if (needed == _shimmerController.isAnimating) return; + if (needed) { + _shimmerController.repeat(); + } else { + _shimmerController.stop(); + } + } + int get _folderPageCount => _folders.isEmpty ? 1 : _folders.length; int get _selectedFolderIndex { diff --git a/lib/frontend/screens/chats/folder_edit_sheet.dart b/lib/frontend/screens/chats/folder_edit_sheet.dart index e7c3e2a..a00c89c 100644 --- a/lib/frontend/screens/chats/folder_edit_sheet.dart +++ b/lib/frontend/screens/chats/folder_edit_sheet.dart @@ -392,8 +392,13 @@ class _FolderEditSheetState extends State<_FolderEditSheet> { color: cs.onSurfaceVariant, size: 20, ), + prefixIconConstraints: const BoxConstraints( + minWidth: 48, + minHeight: 0, + ), isDense: true, border: InputBorder.none, + contentPadding: const EdgeInsets.symmetric(vertical: 14), ), ), ), diff --git a/lib/frontend/widgets/spectrum_background.dart b/lib/frontend/widgets/spectrum_background.dart index 1e7fe80..c38a18a 100644 --- a/lib/frontend/widgets/spectrum_background.dart +++ b/lib/frontend/widgets/spectrum_background.dart @@ -1,6 +1,5 @@ import 'dart:math' as math; import 'dart:typed_data'; -import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -320,9 +319,6 @@ class _SpectrumPalette { bool uniform = true; bool _targetUniform = true; - ui.Shader? _shader; - double _shaderLeft = double.nan; - double _shaderRight = double.nan; static void _writeUniform(Float32List channels, Color color) { for (var i = 0; i < channels.length; i += 3) { @@ -418,21 +414,21 @@ class _SpectrumPalette { ); } uniform = false; - _shader = null; } - ui.Shader shaderFor(double left, double right) { - final cached = _shader; - if (cached != null && _shaderLeft == left && _shaderRight == right) { - return cached; - } - _shaderLeft = left; - _shaderRight = right; - return _shader = ui.Gradient.linear( - Offset(left, 0), - Offset(right, 0), - colors, - _stops, + Color sampleAt(double t) { + if (t <= 0) return colors.first; + if (t >= 1) return colors.last; + final scaled = t * (stopCount - 1); + final lower = scaled.floor(); + final fraction = scaled - lower; + final a = lower * 3; + final b = a + 3; + return Color.from( + alpha: 1, + red: _current[a] + (_current[b] - _current[a]) * fraction, + green: _current[a + 1] + (_current[b + 1] - _current[a + 1]) * fraction, + blue: _current[a + 2] + (_current[b + 2] - _current[a + 2]) * fraction, ); } } @@ -463,17 +459,21 @@ class _SpectrumPainter extends CustomPainter { final maxHeight = size.height * SpectrumTuning.heightFraction; final baseline = size.height; + final uniform = palette.uniform; + final span = zoneRight - zoneLeft; final paint = Paint(); - if (palette.uniform) { - paint.color = palette.colors.first; - } else { - paint.shader = palette.shaderFor(zoneLeft, zoneRight); - } + if (uniform) paint.color = palette.colors.first; for (var i = 0; i < heights.length; i++) { final height = heights[i] * maxHeight; if (height < _minVisibleHeight) continue; final left = leftInset + pitch * i; + if (!uniform) { + final center = left + SpectrumTuning.barWidth / 2; + paint.color = palette.sampleAt( + span <= 0 ? 0 : (center - zoneLeft) / span, + ); + } canvas.drawRect( Rect.fromLTRB( left, diff --git a/pubspec.lock b/pubspec.lock index 4ffe3c3..2b927dc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -857,10 +857,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867" url: "https://pub.dev" source: hosted - version: "0.20.2" + version: "0.20.3" jni: dependency: transitive description: @@ -992,10 +992,10 @@ packages: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.20" material_color_utilities: dependency: transitive description: @@ -1064,10 +1064,10 @@ packages: dependency: transitive description: name: meta - sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" mime: dependency: transitive description: @@ -1685,10 +1685,10 @@ packages: dependency: transitive description: name: test_api - sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.12" timezone: dependency: "direct main" description: @@ -1829,10 +1829,10 @@ packages: dependency: transitive description: name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" video_player: dependency: "direct main" description: