diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 915886e..27f4861 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,6 +25,12 @@ jobs: - name: Get dependencies run: flutter pub get + - name: Analyze + run: flutter analyze --no-fatal-infos + + - name: Test + run: flutter test + - name: Build Linux release run: flutter build linux --release diff --git a/deb/usr/share/applications/imajviewer.desktop b/deb/usr/share/applications/imajviewer.desktop index 8a67120..2e20fee 100644 --- a/deb/usr/share/applications/imajviewer.desktop +++ b/deb/usr/share/applications/imajviewer.desktop @@ -8,4 +8,4 @@ Terminal=false Categories=Graphics;Viewer;RasterGraphics; MimeType=image/png;image/jpeg;image/webp;image/bmp;image/gif;image/jpg;image/vnd.wap.wbmp; StartupNotify=false -StartupWMClass=Com.example.imajviewer +StartupWMClass=Com.softmediadesign.imajviewer diff --git a/dist/imajviewer_1.1.0_amd64.deb b/dist/imajviewer_1.1.0_amd64.deb index 39ebc82..53a72c3 100644 Binary files a/dist/imajviewer_1.1.0_amd64.deb and b/dist/imajviewer_1.1.0_amd64.deb differ diff --git a/imajviewer.png b/imajviewer.png index c15af54..ae34c63 100644 Binary files a/imajviewer.png and b/imajviewer.png differ diff --git a/install.sh b/install.sh index f541e03..80a1048 100755 --- a/install.sh +++ b/install.sh @@ -92,7 +92,7 @@ Terminal=false Categories=Graphics;Viewer;RasterGraphics; MimeType=image/png;image/jpeg;image/webp;image/bmp;image/gif;image/jpg;image/vnd.wap.wbmp; StartupNotify=false -StartupWMClass=Com.example.imajviewer +StartupWMClass=Com.softmediadesign.imajviewer EOF ok "${DESKTOP_FILE}" diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 0000000..15338f2 --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,3 @@ +arb-dir: lib/l10n +template-arb-file: app_en.arb +output-localization-file: app_localizations.dart diff --git a/lib/app.dart b/lib/app.dart index 3bc27f9..31f0953 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; import 'screens/viewer_screen.dart'; +import 'l10n/app_localizations.dart'; class ImajViewerApp extends StatelessWidget { final List initialFiles; @@ -11,6 +13,8 @@ class ImajViewerApp extends StatelessWidget { return MaterialApp( title: 'imajViewer', debugShowCheckedModeBanner: false, + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, theme: ThemeData( brightness: Brightness.dark, scaffoldBackgroundColor: const Color(0xFF1a1a1a), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb new file mode 100644 index 0000000..6996426 --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,15 @@ +{ + "@@locale": "en", + "settingsTitle": "Settings", + "sortBy": "Sort by", + "sortByTime": "By time", + "sortByName": "By name", + "appDescription": "Ultra-lightweight and fast image viewer. Open images and use arrows or keyboard keys to navigate.", + "shortcuts": "Shortcuts", + "shortcutsList": "• Left/Right arrow — previous/next image\n• Ctrl+Q — close window\n• Ctrl+Shift+Q — close all windows\n• Double click — toggle fill/fit\n• Right-drag — contrast\n• Shift+right-drag — rotate\n• Ctrl+right-drag — saturation\n• Ctrl+Shift+right-drag — brightness", + "print": "Print", + "close": "Close", + "dragDropHint": "Drag images here\nor press Ctrl+O to open", + "dropHere": "Drop", + "imageLoadError": "Failed to load image" +} diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart new file mode 100644 index 0000000..53d2ef2 --- /dev/null +++ b/lib/l10n/app_localizations.dart @@ -0,0 +1,206 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart' as intl; + +import 'app_localizations_en.dart'; +import 'app_localizations_tr.dart'; + +// ignore_for_file: type=lint + +/// Callers can lookup localized strings with an instance of AppLocalizations +/// returned by `AppLocalizations.of(context)`. +/// +/// Applications need to include `AppLocalizations.delegate()` in their app's +/// `localizationDelegates` list, and the locales they support in the app's +/// `supportedLocales` list. For example: +/// +/// ```dart +/// import 'l10n/app_localizations.dart'; +/// +/// return MaterialApp( +/// localizationsDelegates: AppLocalizations.localizationsDelegates, +/// supportedLocales: AppLocalizations.supportedLocales, +/// home: MyApplicationHome(), +/// ); +/// ``` +/// +/// ## Update pubspec.yaml +/// +/// Please make sure to update your pubspec.yaml to include the following +/// packages: +/// +/// ```yaml +/// dependencies: +/// # Internationalization support. +/// flutter_localizations: +/// sdk: flutter +/// intl: any # Use the pinned version from flutter_localizations +/// +/// # Rest of dependencies +/// ``` +/// +/// ## iOS Applications +/// +/// iOS applications define key application metadata, including supported +/// locales, in an Info.plist file that is built into the application bundle. +/// To configure the locales supported by your app, you’ll need to edit this +/// file. +/// +/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. +/// Then, in the Project Navigator, open the Info.plist file under the Runner +/// project’s Runner folder. +/// +/// Next, select the Information Property List item, select Add Item from the +/// Editor menu, then select Localizations from the pop-up menu. +/// +/// Select and expand the newly-created Localizations item then, for each +/// locale your application supports, add a new item and select the locale +/// you wish to add from the pop-up menu in the Value field. This list should +/// be consistent with the languages listed in the AppLocalizations.supportedLocales +/// property. +abstract class AppLocalizations { + AppLocalizations(String locale) + : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + + final String localeName; + + static AppLocalizations? of(BuildContext context) { + return Localizations.of(context, AppLocalizations); + } + + static const LocalizationsDelegate delegate = + _AppLocalizationsDelegate(); + + /// A list of this localizations delegate along with the default localizations + /// delegates. + /// + /// Returns a list of localizations delegates containing this delegate along with + /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, + /// and GlobalWidgetsLocalizations.delegate. + /// + /// Additional delegates can be added by appending to this list in + /// MaterialApp. This list does not have to be used at all if a custom list + /// of delegates is preferred or required. + static const List> localizationsDelegates = + >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; + + /// A list of this localizations delegate's supported locales. + static const List supportedLocales = [ + Locale('en'), + Locale('tr'), + ]; + + /// No description provided for @settingsTitle. + /// + /// In en, this message translates to: + /// **'Settings'** + String get settingsTitle; + + /// No description provided for @sortBy. + /// + /// In en, this message translates to: + /// **'Sort by'** + String get sortBy; + + /// No description provided for @sortByTime. + /// + /// In en, this message translates to: + /// **'By time'** + String get sortByTime; + + /// No description provided for @sortByName. + /// + /// In en, this message translates to: + /// **'By name'** + String get sortByName; + + /// No description provided for @appDescription. + /// + /// In en, this message translates to: + /// **'Ultra-lightweight and fast image viewer. Open images and use arrows or keyboard keys to navigate.'** + String get appDescription; + + /// No description provided for @shortcuts. + /// + /// In en, this message translates to: + /// **'Shortcuts'** + String get shortcuts; + + /// No description provided for @shortcutsList. + /// + /// In en, this message translates to: + /// **'• Left/Right arrow — previous/next image\n• Ctrl+Q — close window\n• Ctrl+Shift+Q — close all windows\n• Double click — toggle fill/fit\n• Right-drag — contrast\n• Shift+right-drag — rotate\n• Ctrl+right-drag — saturation\n• Ctrl+Shift+right-drag — brightness'** + String get shortcutsList; + + /// No description provided for @print. + /// + /// In en, this message translates to: + /// **'Print'** + String get print; + + /// No description provided for @close. + /// + /// In en, this message translates to: + /// **'Close'** + String get close; + + /// No description provided for @dragDropHint. + /// + /// In en, this message translates to: + /// **'Drag images here\nor press Ctrl+O to open'** + String get dragDropHint; + + /// No description provided for @dropHere. + /// + /// In en, this message translates to: + /// **'Drop'** + String get dropHere; + + /// No description provided for @imageLoadError. + /// + /// In en, this message translates to: + /// **'Failed to load image'** + String get imageLoadError; +} + +class _AppLocalizationsDelegate + extends LocalizationsDelegate { + const _AppLocalizationsDelegate(); + + @override + Future load(Locale locale) { + return SynchronousFuture(lookupAppLocalizations(locale)); + } + + @override + bool isSupported(Locale locale) => + ['en', 'tr'].contains(locale.languageCode); + + @override + bool shouldReload(_AppLocalizationsDelegate old) => false; +} + +AppLocalizations lookupAppLocalizations(Locale locale) { + // Lookup logic when only language code is specified. + switch (locale.languageCode) { + case 'en': + return AppLocalizationsEn(); + case 'tr': + return AppLocalizationsTr(); + } + + throw FlutterError( + 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' + 'an issue with the localizations generation tool. Please file an issue ' + 'on GitHub with a reproducible sample app and the gen-l10n configuration ' + 'that was used.', + ); +} diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart new file mode 100644 index 0000000..5ec2cdf --- /dev/null +++ b/lib/l10n/app_localizations_en.dart @@ -0,0 +1,48 @@ +// ignore: unused_import +import 'package:intl/intl.dart' as intl; +import 'app_localizations.dart'; + +// ignore_for_file: type=lint + +/// The translations for English (`en`). +class AppLocalizationsEn extends AppLocalizations { + AppLocalizationsEn([String locale = 'en']) : super(locale); + + @override + String get settingsTitle => 'Settings'; + + @override + String get sortBy => 'Sort by'; + + @override + String get sortByTime => 'By time'; + + @override + String get sortByName => 'By name'; + + @override + String get appDescription => + 'Ultra-lightweight and fast image viewer. Open images and use arrows or keyboard keys to navigate.'; + + @override + String get shortcuts => 'Shortcuts'; + + @override + String get shortcutsList => + '• Left/Right arrow — previous/next image\n• Ctrl+Q — close window\n• Ctrl+Shift+Q — close all windows\n• Double click — toggle fill/fit\n• Right-drag — contrast\n• Shift+right-drag — rotate\n• Ctrl+right-drag — saturation\n• Ctrl+Shift+right-drag — brightness'; + + @override + String get print => 'Print'; + + @override + String get close => 'Close'; + + @override + String get dragDropHint => 'Drag images here\nor press Ctrl+O to open'; + + @override + String get dropHere => 'Drop'; + + @override + String get imageLoadError => 'Failed to load image'; +} diff --git a/lib/l10n/app_localizations_tr.dart b/lib/l10n/app_localizations_tr.dart new file mode 100644 index 0000000..b1b048a --- /dev/null +++ b/lib/l10n/app_localizations_tr.dart @@ -0,0 +1,49 @@ +// ignore: unused_import +import 'package:intl/intl.dart' as intl; +import 'app_localizations.dart'; + +// ignore_for_file: type=lint + +/// The translations for Turkish (`tr`). +class AppLocalizationsTr extends AppLocalizations { + AppLocalizationsTr([String locale = 'tr']) : super(locale); + + @override + String get settingsTitle => 'Ayarlar'; + + @override + String get sortBy => 'Sıralama'; + + @override + String get sortByTime => 'Zamana göre'; + + @override + String get sortByName => 'İsme göre'; + + @override + String get appDescription => + 'Ultra hafif ve hızlı resim görüntüleyici. Görselleri açın, gezinti için okları veya klavye tuşlarını kullanın.'; + + @override + String get shortcuts => 'Kısayollar'; + + @override + String get shortcutsList => + '• Sol/Sağ ok — önceki/sonraki resim\n• Ctrl+Q — pencereyi kapat\n• Ctrl+Shift+Q — tüm pencereleri kapat\n• Çift tık — doldur/sığdır geçişi\n• Sağ tık sürükle — kontrast\n• Shift+sağ tık — döndür\n• Ctrl+sağ tık — doygunluk\n• Ctrl+Shift+sağ tık — parlaklık'; + + @override + String get print => 'Yazdır'; + + @override + String get close => 'Kapat'; + + @override + String get dragDropHint => + 'Resimleri buraya sürükleyin\nveya Ctrl+O ile açın'; + + @override + String get dropHere => 'Bırakın'; + + @override + String get imageLoadError => 'Resim yüklenemedi'; +} diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb new file mode 100644 index 0000000..173da9f --- /dev/null +++ b/lib/l10n/app_tr.arb @@ -0,0 +1,15 @@ +{ + "@@locale": "tr", + "settingsTitle": "Ayarlar", + "sortBy": "Sıralama", + "sortByTime": "Zamana göre", + "sortByName": "İsme göre", + "appDescription": "Ultra hafif ve hızlı resim görüntüleyici. Görselleri açın, gezinti için okları veya klavye tuşlarını kullanın.", + "shortcuts": "Kısayollar", + "shortcutsList": "• Sol/Sağ ok — önceki/sonraki resim\n• Ctrl+Q — pencereyi kapat\n• Ctrl+Shift+Q — tüm pencereleri kapat\n• Çift tık — doldur/sığdır geçişi\n• Sağ tık sürükle — kontrast\n• Shift+sağ tık — döndür\n• Ctrl+sağ tık — doygunluk\n• Ctrl+Shift+sağ tık — parlaklık", + "print": "Yazdır", + "close": "Kapat", + "dragDropHint": "Resimleri buraya sürükleyin\nveya Ctrl+O ile açın", + "dropHere": "Bırakın", + "imageLoadError": "Resim yüklenemedi" +} diff --git a/lib/screens/viewer_screen.dart b/lib/screens/viewer_screen.dart index 6689287..411402b 100644 --- a/lib/screens/viewer_screen.dart +++ b/lib/screens/viewer_screen.dart @@ -13,6 +13,7 @@ import '../widgets/image_canvas.dart'; import '../widgets/window_resize_zones.dart'; import '../shortcuts/app_shortcuts.dart'; import '../services/window_persistence.dart'; +import '../l10n/app_localizations.dart'; class ViewerScreen extends StatefulWidget { final List initialFiles; @@ -95,22 +96,22 @@ class _ViewerScreenState extends State with WindowListener { builder: (context) => StatefulBuilder( builder: (context, setDialogState) => AlertDialog( backgroundColor: const Color(0xFF2a2a2a), - title: const Text('Ayarlar', - style: TextStyle(color: Colors.white, fontSize: 18)), + title: Text(AppLocalizations.of(context)!.settingsTitle, + style: const TextStyle(color: Colors.white, fontSize: 18)), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text('Sıralama', - style: TextStyle(color: Colors.white70, fontSize: 13)), + Text(AppLocalizations.of(context)!.sortBy, + style: const TextStyle(color: Colors.white70, fontSize: 13)), RadioListTile( value: false, groupValue: ImageManager.instance.sortByName, dense: true, activeColor: Colors.blueAccent, - title: const Text('Zamana göre', - style: TextStyle(color: Colors.white, fontSize: 14)), + title: Text(AppLocalizations.of(context)!.sortByTime, + style: const TextStyle(color: Colors.white, fontSize: 14)), onChanged: (v) { ImageManager.instance.setSortByName(v!); setDialogState(() {}); @@ -121,8 +122,8 @@ class _ViewerScreenState extends State with WindowListener { groupValue: ImageManager.instance.sortByName, dense: true, activeColor: Colors.blueAccent, - title: const Text('İsme göre', - style: TextStyle(color: Colors.white, fontSize: 14)), + title: Text(AppLocalizations.of(context)!.sortByName, + style: const TextStyle(color: Colors.white, fontSize: 14)), onChanged: (v) { ImageManager.instance.setSortByName(v!); setDialogState(() {}); @@ -131,25 +132,17 @@ class _ViewerScreenState extends State with WindowListener { const Divider(color: Colors.white24, height: 24), const Text('imajViewer', style: TextStyle(color: Colors.white, fontSize: 15)), const SizedBox(height: 4), - const Text( - 'Ultra hafif ve hızlı resim görüntüleyici. ' - 'Görselleri açın, gezinti için okları veya klavye tuşlarını kullanın.', - style: TextStyle(color: Colors.white70, fontSize: 13, height: 1.5), + Text( + AppLocalizations.of(context)!.appDescription, + style: const TextStyle(color: Colors.white70, fontSize: 13, height: 1.5), ), const SizedBox(height: 12), - const Text('Kısayollar', - style: TextStyle(color: Colors.white70, fontSize: 13)), + Text(AppLocalizations.of(context)!.shortcuts, + style: const TextStyle(color: Colors.white70, fontSize: 13)), const SizedBox(height: 4), - const Text( - '• Sol/Sağ ok — önceki/sonraki resim\n' - '• Ctrl+Q — pencereyi kapat\n' - '• Ctrl+Shift+Q — tüm pencereleri kapat\n' - '• Çift tık — doldur/sığdır geçişi\n' - '• Sağ tık sürükle — kontrast\n' - '• Shift+sağ tık — döndür\n' - '• Ctrl+sağ tık — doygunluk\n' - '• Ctrl+Shift+sağ tık — parlaklık', - style: TextStyle(color: Colors.white70, fontSize: 13, height: 1.6), + Text( + AppLocalizations.of(context)!.shortcutsList, + style: const TextStyle(color: Colors.white70, fontSize: 13, height: 1.6), ), ], ), @@ -161,12 +154,12 @@ class _ViewerScreenState extends State with WindowListener { _printImage(); }, icon: const Icon(Icons.print, color: Colors.white70, size: 18), - label: const Text('Yazdır', - style: TextStyle(color: Colors.white70)), + label: Text(AppLocalizations.of(context)!.print, + style: const TextStyle(color: Colors.white70)), ), TextButton( onPressed: () => Navigator.pop(context), - child: const Text('Kapat', style: TextStyle(color: Colors.white70)), + child: Text(AppLocalizations.of(context)!.close, style: const TextStyle(color: Colors.white70)), ), ], ), @@ -232,15 +225,16 @@ class _ViewerScreenState extends State with WindowListener { ? ImageCanvas( filePath: ImageManager.instance.currentImagePath, ) - : const Center( + : Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.image, size: 64, color: Colors.white24), - SizedBox(height: 16), - Text('Resimleri buraya sürükleyin\nveya Ctrl+O ile açın', + const Icon(Icons.image, size: 64, color: Colors.white24), + const SizedBox(height: 16), + Text(AppLocalizations.of(context)!.dragDropHint, + key: const Key('dragDropHint'), textAlign: TextAlign.center, - style: TextStyle(color: Colors.white38, fontSize: 16)), + style: const TextStyle(color: Colors.white38, fontSize: 16)), ], ), ), @@ -280,8 +274,8 @@ class _ViewerScreenState extends State with WindowListener { borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.blueAccent, width: 2), ), - child: const Text('Bırakın', - style: TextStyle(color: Colors.white, fontSize: 24)), + child: Text(AppLocalizations.of(context)!.dropHere, + style: const TextStyle(color: Colors.white, fontSize: 24)), ), ), ), diff --git a/lib/widgets/image_canvas.dart b/lib/widgets/image_canvas.dart index d56eaed..0a53d6b 100644 --- a/lib/widgets/image_canvas.dart +++ b/lib/widgets/image_canvas.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; +import '../l10n/app_localizations.dart'; class ImageCanvas extends StatefulWidget { final String filePath; @@ -203,7 +204,7 @@ class _ImageCanvasState extends State { final double cy = (vy - _ty) / _sc; const double factor = 1.1; final double rawSc = _sc * (e.scrollDelta.dy < 0 ? factor : 1.0 / factor); - final double newSc = rawSc.clamp(1.0, 10.0); + final double newSc = rawSc.clamp(1.0, 20.0); if (_angle == 0) { _tx = _tx + cx * _sc - cx * newSc; _ty = _ty + cy * _sc - cy * newSc; @@ -373,7 +374,7 @@ class _ImageCanvasState extends State { Widget _buildImage() { final longest = _vpSize.longestSide; - final cacheWidth = longest > 0 ? (longest * 2).round() : null; + final cacheWidth = longest > 0 ? (longest * _sc * 2).round() : null; if (_cachedPath != widget.filePath || _cachedCacheWidth != cacheWidth) { _cachedPath = widget.filePath; _cachedCacheWidth = cacheWidth; @@ -388,6 +389,7 @@ class _ImageCanvasState extends State { image: provider, fit: _isFilled ? BoxFit.cover : BoxFit.contain, filterQuality: FilterQuality.high, + gaplessPlayback: true, errorBuilder: (_, _, _) => _errorWidget(), ); } @@ -494,13 +496,14 @@ class _ImageCanvasState extends State { } Widget _errorWidget() { - return const Center( + return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.broken_image, size: 48, color: Colors.white38), - SizedBox(height: 8), - Text('Resim yüklenemedi', style: TextStyle(color: Colors.white38)), + const Icon(Icons.broken_image, size: 48, color: Colors.white38), + const SizedBox(height: 8), + Text(AppLocalizations.of(context)!.imageLoadError, + style: const TextStyle(color: Colors.white38)), ], ), ); diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 704f574..7c3398c 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -7,7 +7,7 @@ project(runner LANGUAGES CXX) set(BINARY_NAME "imajviewer") # The unique GTK application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.imajviewer") +set(APPLICATION_ID "com.softmediadesign.imajviewer") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. diff --git a/pubspec.lock b/pubspec.lock index 4dfb7ba..9274b10 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -150,6 +150,11 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -200,6 +205,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.9.1" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" json_annotation: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b442938..100bc96 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: imajviewer -description: "Ultra hafif görüntü izleyici" +description: "Ultra-lightweight image viewer for Linux and Windows." publish_to: 'none' version: 1.1.0+3 @@ -17,6 +17,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter window_manager: ^0.4.3 screen_retriever: ^0.2.2 file_picker: ^8.0.0 @@ -33,3 +35,4 @@ dev_dependencies: flutter: uses-material-design: true + generate: true diff --git a/test/widget_test.dart b/test/widget_test.dart index c0a74b7..8494be3 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:imajviewer/app.dart'; @@ -9,7 +10,7 @@ void main() { // Pump pending timers (Future.delayed in initState + polling) await tester.pump(const Duration(milliseconds: 500)); - // Should show drag-drop hint text - expect(find.textContaining('sürükleyin'), findsOneWidget); + // Should show drag-drop hint (Key-based, locale independent) + expect(find.byKey(const Key('dragDropHint')), findsOneWidget); }); } diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index c2ad265..6f2bc02 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -89,11 +89,11 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "com.example" "\0" + VALUE "CompanyName", "com.softmediadesign" "\0" VALUE "FileDescription", "imajviewer" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "imajviewer" "\0" - VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 com.softmediadesign. All rights reserved." "\0" VALUE "OriginalFilename", "imajviewer.exe" "\0" VALUE "ProductName", "imajviewer" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0"