mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Add Slovenian localization for trail management and device configuration
- Updated `app_localizations_sl.dart` with new strings for trail management, device information, and error messages. - Enhanced `app_sl.arb` with corresponding translations for the new strings. - Refactored `device_config_screen.dart` to utilize localized strings for device information and error handling. - Modified `map_tab.dart` to remove unused trail stats overlay. - Improved `ble_response_handler.dart` to include additional debug information for parsed contacts and advertisements. - Updated `trail_controls.dart` to use localized strings for trail management UI, including trail visibility toggle and confirmation dialogs.
This commit is contained in:
@@ -17,7 +17,11 @@
|
|||||||
"Bash(flutter analyze lib/main.dart)",
|
"Bash(flutter analyze lib/main.dart)",
|
||||||
"Bash(flutter analyze lib/providers/app_provider.dart lib/services/meshcore_ble_service.dart)",
|
"Bash(flutter analyze lib/providers/app_provider.dart lib/services/meshcore_ble_service.dart)",
|
||||||
"Bash(flutter analyze lib/services/meshcore_ble_service.dart)",
|
"Bash(flutter analyze lib/services/meshcore_ble_service.dart)",
|
||||||
"Bash(flutter analyze lib/services/meshcore_ble_service.dart lib/services/location_tracking_service.dart)"
|
"Bash(flutter analyze lib/services/meshcore_ble_service.dart lib/services/location_tracking_service.dart)",
|
||||||
|
"Bash(flutter analyze lib/widgets/map/trail_controls.dart lib/screens/map_tab.dart)",
|
||||||
|
"Bash(flutter analyze lib/screens/device_config_screen.dart)",
|
||||||
|
"Bash(flutter analyze lib/services/ble/ble_response_handler.dart)",
|
||||||
|
"Bash(flutter analyze)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
Binary file not shown.
BIN
ios/Runner.ipa
BIN
ios/Runner.ipa
Binary file not shown.
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000218">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000178">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.276257">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.251467">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="134.535005">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="121.847246">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_testflight" time="9.956839">
|
<testcase classname="fastlane.lanes" name="3: upload_to_testflight" time="10.210838">
|
||||||
|
|
||||||
<failure message="/opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/actions/actions_helper.rb:67:in 'Fastlane::Actions.execute_action' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:255:in 'block in Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:229:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:229:in 'Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:157:in 'Fastlane::Runner#trigger_action_by_name' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:159:in 'Fastlane::FastFile#method_missing' Fastfile:23:in 'block (2 levels) in Fastlane::FastFile#parsing_binding' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in 'Fastlane::CLIToolsDistributor.take_off' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/bin/fastlane:23:in '<top (required)>' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in 'Kernel#load' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in '<main>' Error uploading ipa file: [Application Loader Error Output]: The call to the altool completed with a non-zero exit status: 1. This indicates a failure." />
|
<failure message="/opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/actions/actions_helper.rb:67:in 'Fastlane::Actions.execute_action' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:255:in 'block in Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:229:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:229:in 'Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:157:in 'Fastlane::Runner#trigger_action_by_name' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:159:in 'Fastlane::FastFile#method_missing' Fastfile:23:in 'block (2 levels) in Fastlane::FastFile#parsing_binding' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in 'Fastlane::CLIToolsDistributor.take_off' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/bin/fastlane:23:in '<top (required)>' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in 'Kernel#load' /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in '<main>' Error uploading ipa file: [Application Loader Error Output]: The call to the altool completed with a non-zero exit status: 1. This indicates a failure." />
|
||||||
|
|
||||||
|
|||||||
2100
lib/l10n/app_de.arb
Normal file
2100
lib/l10n/app_de.arb
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1886,5 +1886,215 @@
|
|||||||
"offlineLayers": "Offline Layers",
|
"offlineLayers": "Offline Layers",
|
||||||
"@offlineLayers": {
|
"@offlineLayers": {
|
||||||
"description": "Section header for offline map layers (MBTiles)"
|
"description": "Section header for offline map layers (MBTiles)"
|
||||||
|
},
|
||||||
|
|
||||||
|
"locationTrail": "Location Trail",
|
||||||
|
"@locationTrail": {
|
||||||
|
"description": "Location trail title"
|
||||||
|
},
|
||||||
|
|
||||||
|
"showTrailOnMap": "Show Trail on Map",
|
||||||
|
"@showTrailOnMap": {
|
||||||
|
"description": "Toggle to show/hide trail on map"
|
||||||
|
},
|
||||||
|
|
||||||
|
"trailVisible": "Trail is visible on the map",
|
||||||
|
"@trailVisible": {
|
||||||
|
"description": "Trail visibility status - visible"
|
||||||
|
},
|
||||||
|
|
||||||
|
"trailHiddenRecording": "Trail is hidden (still recording)",
|
||||||
|
"@trailHiddenRecording": {
|
||||||
|
"description": "Trail visibility status - hidden but recording"
|
||||||
|
},
|
||||||
|
|
||||||
|
"distance": "Distance",
|
||||||
|
"@distance": {
|
||||||
|
"description": "Distance label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"duration": "Duration",
|
||||||
|
"@duration": {
|
||||||
|
"description": "Duration label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"points": "Points",
|
||||||
|
"@points": {
|
||||||
|
"description": "Trail points count label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"clearTrail": "Clear Trail",
|
||||||
|
"@clearTrail": {
|
||||||
|
"description": "Button to clear location trail"
|
||||||
|
},
|
||||||
|
|
||||||
|
"clearTrailQuestion": "Clear Trail?",
|
||||||
|
"@clearTrailQuestion": {
|
||||||
|
"description": "Confirmation dialog title"
|
||||||
|
},
|
||||||
|
|
||||||
|
"clearTrailConfirmation": "Are you sure you want to clear the current location trail? This action cannot be undone.",
|
||||||
|
"@clearTrailConfirmation": {
|
||||||
|
"description": "Confirmation dialog message"
|
||||||
|
},
|
||||||
|
|
||||||
|
"noTrailRecorded": "No trail recorded yet",
|
||||||
|
"@noTrailRecorded": {
|
||||||
|
"description": "Message when no trail exists"
|
||||||
|
},
|
||||||
|
|
||||||
|
"startTrackingToRecord": "Start location tracking to record your trail",
|
||||||
|
"@startTrackingToRecord": {
|
||||||
|
"description": "Instructions to start trail recording"
|
||||||
|
},
|
||||||
|
|
||||||
|
"trailControls": "Trail Controls",
|
||||||
|
"@trailControls": {
|
||||||
|
"description": "Trail controls tooltip"
|
||||||
|
},
|
||||||
|
|
||||||
|
"deviceInformation": "Device Information",
|
||||||
|
"@deviceInformation": {
|
||||||
|
"description": "Device information section header"
|
||||||
|
},
|
||||||
|
|
||||||
|
"bleName": "BLE Name",
|
||||||
|
"@bleName": {
|
||||||
|
"description": "Bluetooth Low Energy device name label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"meshName": "Mesh Name",
|
||||||
|
"@meshName": {
|
||||||
|
"description": "Mesh network name label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"notSet": "Not set",
|
||||||
|
"@notSet": {
|
||||||
|
"description": "Label when a value is not set"
|
||||||
|
},
|
||||||
|
|
||||||
|
"model": "Model",
|
||||||
|
"@model": {
|
||||||
|
"description": "Device model label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"version": "Version",
|
||||||
|
"@version": {
|
||||||
|
"description": "Version label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"buildDate": "Build Date",
|
||||||
|
"@buildDate": {
|
||||||
|
"description": "Firmware build date label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"firmware": "Firmware",
|
||||||
|
"@firmware": {
|
||||||
|
"description": "Firmware label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"maxContacts": "Max Contacts",
|
||||||
|
"@maxContacts": {
|
||||||
|
"description": "Maximum contacts capacity label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"maxChannels": "Max Channels",
|
||||||
|
"@maxChannels": {
|
||||||
|
"description": "Maximum channels capacity label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"publicInfo": "Public Info",
|
||||||
|
"@publicInfo": {
|
||||||
|
"description": "Public information section header"
|
||||||
|
},
|
||||||
|
|
||||||
|
"meshNetworkName": "Mesh Network Name",
|
||||||
|
"@meshNetworkName": {
|
||||||
|
"description": "Mesh network name field label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"nameBroadcastInMesh": "Name broadcast in mesh advertisements",
|
||||||
|
"@nameBroadcastInMesh": {
|
||||||
|
"description": "Helper text for mesh network name field"
|
||||||
|
},
|
||||||
|
|
||||||
|
"telemetryAndLocationSharing": "Telemetry & Location Sharing",
|
||||||
|
"@telemetryAndLocationSharing": {
|
||||||
|
"description": "Telemetry and location sharing toggle label"
|
||||||
|
},
|
||||||
|
|
||||||
|
"lat": "Lat",
|
||||||
|
"@lat": {
|
||||||
|
"description": "Latitude field label (short form)"
|
||||||
|
},
|
||||||
|
|
||||||
|
"lon": "Lon",
|
||||||
|
"@lon": {
|
||||||
|
"description": "Longitude field label (short form)"
|
||||||
|
},
|
||||||
|
|
||||||
|
"useCurrentLocation": "Use current location",
|
||||||
|
"@useCurrentLocation": {
|
||||||
|
"description": "Tooltip for use current location button"
|
||||||
|
},
|
||||||
|
|
||||||
|
"noneUnknown": "None/Unknown",
|
||||||
|
"@noneUnknown": {
|
||||||
|
"description": "Device type: none or unknown"
|
||||||
|
},
|
||||||
|
|
||||||
|
"chatNode": "Chat Node",
|
||||||
|
"@chatNode": {
|
||||||
|
"description": "Device type: chat node"
|
||||||
|
},
|
||||||
|
|
||||||
|
"repeater": "Repeater",
|
||||||
|
"@repeater": {
|
||||||
|
"description": "Device type: repeater"
|
||||||
|
},
|
||||||
|
|
||||||
|
"roomChannel": "Room/Channel",
|
||||||
|
"@roomChannel": {
|
||||||
|
"description": "Device type: room or channel"
|
||||||
|
},
|
||||||
|
|
||||||
|
"typeNumber": "Type {number}",
|
||||||
|
"@typeNumber": {
|
||||||
|
"description": "Generic device type with number",
|
||||||
|
"placeholders": {
|
||||||
|
"number": {
|
||||||
|
"type": "int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"copiedToClipboardShort": "Copied {label} to clipboard",
|
||||||
|
"@copiedToClipboardShort": {
|
||||||
|
"description": "Short success message when copying to clipboard",
|
||||||
|
"placeholders": {
|
||||||
|
"label": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"failedToSave": "Failed to save: {error}",
|
||||||
|
"@failedToSave": {
|
||||||
|
"description": "Generic error message for save failures",
|
||||||
|
"placeholders": {
|
||||||
|
"error": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"failedToGetLocation": "Failed to get location: {error}",
|
||||||
|
"@failedToGetLocation": {
|
||||||
|
"description": "Error message when getting location fails",
|
||||||
|
"placeholders": {
|
||||||
|
"error": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2095
lib/l10n/app_es.arb
Normal file
2095
lib/l10n/app_es.arb
Normal file
File diff suppressed because it is too large
Load Diff
2100
lib/l10n/app_fr.arb
Normal file
2100
lib/l10n/app_fr.arb
Normal file
File diff suppressed because it is too large
Load Diff
@@ -632,5 +632,81 @@
|
|||||||
|
|
||||||
"onlineLayers": "Mrežni slojevi",
|
"onlineLayers": "Mrežni slojevi",
|
||||||
|
|
||||||
"offlineLayers": "Offline slojevi"
|
"offlineLayers": "Offline slojevi",
|
||||||
|
|
||||||
|
"locationTrail": "Putanja lokacije",
|
||||||
|
|
||||||
|
"showTrailOnMap": "Prikaži putanju na karti",
|
||||||
|
|
||||||
|
"trailVisible": "Putanja je vidljiva na karti",
|
||||||
|
|
||||||
|
"trailHiddenRecording": "Putanja je skrivena (još se snima)",
|
||||||
|
|
||||||
|
"distance": "Udaljenost",
|
||||||
|
|
||||||
|
"duration": "Trajanje",
|
||||||
|
|
||||||
|
"points": "Točke",
|
||||||
|
|
||||||
|
"clearTrail": "Obriši putanju",
|
||||||
|
|
||||||
|
"clearTrailQuestion": "Obrisati putanju?",
|
||||||
|
|
||||||
|
"clearTrailConfirmation": "Jeste li sigurni da želite obrisati trenutnu putanju lokacije? Ova radnja se ne može poništiti.",
|
||||||
|
|
||||||
|
"noTrailRecorded": "Još nije snimljena putanja",
|
||||||
|
|
||||||
|
"startTrackingToRecord": "Pokrenite praćenje lokacije za snimanje putanje",
|
||||||
|
|
||||||
|
"trailControls": "Upravljanje putanjom",
|
||||||
|
|
||||||
|
"deviceInformation": "Informacije o uređaju",
|
||||||
|
|
||||||
|
"bleName": "BLE naziv",
|
||||||
|
|
||||||
|
"meshName": "Mesh naziv",
|
||||||
|
|
||||||
|
"notSet": "Nije postavljeno",
|
||||||
|
|
||||||
|
"model": "Model",
|
||||||
|
|
||||||
|
"version": "Verzija",
|
||||||
|
|
||||||
|
"buildDate": "Datum izgradnje",
|
||||||
|
|
||||||
|
"firmware": "Firmware",
|
||||||
|
|
||||||
|
"maxContacts": "Maks. kontakata",
|
||||||
|
|
||||||
|
"maxChannels": "Maks. kanala",
|
||||||
|
|
||||||
|
"publicInfo": "Javne informacije",
|
||||||
|
|
||||||
|
"meshNetworkName": "Naziv mesh mreže",
|
||||||
|
|
||||||
|
"nameBroadcastInMesh": "Naziv koji se emitira u mesh oglasima",
|
||||||
|
|
||||||
|
"telemetryAndLocationSharing": "Telemetrija i dijeljenje lokacije",
|
||||||
|
|
||||||
|
"lat": "Šir",
|
||||||
|
|
||||||
|
"lon": "Dug",
|
||||||
|
|
||||||
|
"useCurrentLocation": "Koristi trenutnu lokaciju",
|
||||||
|
|
||||||
|
"noneUnknown": "Nema/Nepoznato",
|
||||||
|
|
||||||
|
"chatNode": "Čvorište za razgovor",
|
||||||
|
|
||||||
|
"repeater": "Repetitor",
|
||||||
|
|
||||||
|
"roomChannel": "Soba/Kanal",
|
||||||
|
|
||||||
|
"typeNumber": "Tip {number}",
|
||||||
|
|
||||||
|
"copiedToClipboardShort": "Kopirano {label} u međuspremnik",
|
||||||
|
|
||||||
|
"failedToSave": "Neuspjelo spremanje: {error}",
|
||||||
|
|
||||||
|
"failedToGetLocation": "Neuspjelo dohvaćanje lokacije: {error}"
|
||||||
}
|
}
|
||||||
|
|||||||
2100
lib/l10n/app_it.arb
Normal file
2100
lib/l10n/app_it.arb
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,12 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:intl/intl.dart' as intl;
|
import 'package:intl/intl.dart' as intl;
|
||||||
|
|
||||||
|
import 'app_localizations_de.dart';
|
||||||
import 'app_localizations_en.dart';
|
import 'app_localizations_en.dart';
|
||||||
|
import 'app_localizations_es.dart';
|
||||||
|
import 'app_localizations_fr.dart';
|
||||||
import 'app_localizations_hr.dart';
|
import 'app_localizations_hr.dart';
|
||||||
|
import 'app_localizations_it.dart';
|
||||||
import 'app_localizations_sl.dart';
|
import 'app_localizations_sl.dart';
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
@@ -95,8 +99,12 @@ abstract class AppLocalizations {
|
|||||||
|
|
||||||
/// A list of this localizations delegate's supported locales.
|
/// A list of this localizations delegate's supported locales.
|
||||||
static const List<Locale> supportedLocales = <Locale>[
|
static const List<Locale> supportedLocales = <Locale>[
|
||||||
|
Locale('de'),
|
||||||
Locale('en'),
|
Locale('en'),
|
||||||
|
Locale('es'),
|
||||||
|
Locale('fr'),
|
||||||
Locale('hr'),
|
Locale('hr'),
|
||||||
|
Locale('it'),
|
||||||
Locale('sl'),
|
Locale('sl'),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -2024,6 +2032,228 @@ abstract class AppLocalizations {
|
|||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Offline Layers'**
|
/// **'Offline Layers'**
|
||||||
String get offlineLayers;
|
String get offlineLayers;
|
||||||
|
|
||||||
|
/// Location trail title
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Location Trail'**
|
||||||
|
String get locationTrail;
|
||||||
|
|
||||||
|
/// Toggle to show/hide trail on map
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Show Trail on Map'**
|
||||||
|
String get showTrailOnMap;
|
||||||
|
|
||||||
|
/// Trail visibility status - visible
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Trail is visible on the map'**
|
||||||
|
String get trailVisible;
|
||||||
|
|
||||||
|
/// Trail visibility status - hidden but recording
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Trail is hidden (still recording)'**
|
||||||
|
String get trailHiddenRecording;
|
||||||
|
|
||||||
|
/// Duration label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Duration'**
|
||||||
|
String get duration;
|
||||||
|
|
||||||
|
/// Trail points count label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Points'**
|
||||||
|
String get points;
|
||||||
|
|
||||||
|
/// Button to clear location trail
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Clear Trail'**
|
||||||
|
String get clearTrail;
|
||||||
|
|
||||||
|
/// Confirmation dialog title
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Clear Trail?'**
|
||||||
|
String get clearTrailQuestion;
|
||||||
|
|
||||||
|
/// Confirmation dialog message
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Are you sure you want to clear the current location trail? This action cannot be undone.'**
|
||||||
|
String get clearTrailConfirmation;
|
||||||
|
|
||||||
|
/// Message when no trail exists
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'No trail recorded yet'**
|
||||||
|
String get noTrailRecorded;
|
||||||
|
|
||||||
|
/// Instructions to start trail recording
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Start location tracking to record your trail'**
|
||||||
|
String get startTrackingToRecord;
|
||||||
|
|
||||||
|
/// Trail controls tooltip
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Trail Controls'**
|
||||||
|
String get trailControls;
|
||||||
|
|
||||||
|
/// Device information section header
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Device Information'**
|
||||||
|
String get deviceInformation;
|
||||||
|
|
||||||
|
/// Bluetooth Low Energy device name label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'BLE Name'**
|
||||||
|
String get bleName;
|
||||||
|
|
||||||
|
/// Mesh network name label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Mesh Name'**
|
||||||
|
String get meshName;
|
||||||
|
|
||||||
|
/// Label when a value is not set
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Not set'**
|
||||||
|
String get notSet;
|
||||||
|
|
||||||
|
/// Device model label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Model'**
|
||||||
|
String get model;
|
||||||
|
|
||||||
|
/// Version label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Version'**
|
||||||
|
String get version;
|
||||||
|
|
||||||
|
/// Firmware build date label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Build Date'**
|
||||||
|
String get buildDate;
|
||||||
|
|
||||||
|
/// Firmware label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Firmware'**
|
||||||
|
String get firmware;
|
||||||
|
|
||||||
|
/// Maximum contacts capacity label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Max Contacts'**
|
||||||
|
String get maxContacts;
|
||||||
|
|
||||||
|
/// Maximum channels capacity label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Max Channels'**
|
||||||
|
String get maxChannels;
|
||||||
|
|
||||||
|
/// Public information section header
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Public Info'**
|
||||||
|
String get publicInfo;
|
||||||
|
|
||||||
|
/// Mesh network name field label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Mesh Network Name'**
|
||||||
|
String get meshNetworkName;
|
||||||
|
|
||||||
|
/// Helper text for mesh network name field
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Name broadcast in mesh advertisements'**
|
||||||
|
String get nameBroadcastInMesh;
|
||||||
|
|
||||||
|
/// Telemetry and location sharing toggle label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Telemetry & Location Sharing'**
|
||||||
|
String get telemetryAndLocationSharing;
|
||||||
|
|
||||||
|
/// Latitude field label (short form)
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Lat'**
|
||||||
|
String get lat;
|
||||||
|
|
||||||
|
/// Longitude field label (short form)
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Lon'**
|
||||||
|
String get lon;
|
||||||
|
|
||||||
|
/// Tooltip for use current location button
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Use current location'**
|
||||||
|
String get useCurrentLocation;
|
||||||
|
|
||||||
|
/// Device type: none or unknown
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'None/Unknown'**
|
||||||
|
String get noneUnknown;
|
||||||
|
|
||||||
|
/// Device type: chat node
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Chat Node'**
|
||||||
|
String get chatNode;
|
||||||
|
|
||||||
|
/// Device type: repeater
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Repeater'**
|
||||||
|
String get repeater;
|
||||||
|
|
||||||
|
/// Device type: room or channel
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Room/Channel'**
|
||||||
|
String get roomChannel;
|
||||||
|
|
||||||
|
/// Generic device type with number
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Type {number}'**
|
||||||
|
String typeNumber(int number);
|
||||||
|
|
||||||
|
/// Short success message when copying to clipboard
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Copied {label} to clipboard'**
|
||||||
|
String copiedToClipboardShort(String label);
|
||||||
|
|
||||||
|
/// Generic error message for save failures
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Failed to save: {error}'**
|
||||||
|
String failedToSave(String error);
|
||||||
|
|
||||||
|
/// Error message when getting location fails
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Failed to get location: {error}'**
|
||||||
|
String failedToGetLocation(String error);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class _AppLocalizationsDelegate
|
||||||
@@ -2036,8 +2266,15 @@ class _AppLocalizationsDelegate
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isSupported(Locale locale) =>
|
bool isSupported(Locale locale) => <String>[
|
||||||
<String>['en', 'hr', 'sl'].contains(locale.languageCode);
|
'de',
|
||||||
|
'en',
|
||||||
|
'es',
|
||||||
|
'fr',
|
||||||
|
'hr',
|
||||||
|
'it',
|
||||||
|
'sl',
|
||||||
|
].contains(locale.languageCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||||
@@ -2046,10 +2283,18 @@ class _AppLocalizationsDelegate
|
|||||||
AppLocalizations lookupAppLocalizations(Locale locale) {
|
AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||||
// Lookup logic when only language code is specified.
|
// Lookup logic when only language code is specified.
|
||||||
switch (locale.languageCode) {
|
switch (locale.languageCode) {
|
||||||
|
case 'de':
|
||||||
|
return AppLocalizationsDe();
|
||||||
case 'en':
|
case 'en':
|
||||||
return AppLocalizationsEn();
|
return AppLocalizationsEn();
|
||||||
|
case 'es':
|
||||||
|
return AppLocalizationsEs();
|
||||||
|
case 'fr':
|
||||||
|
return AppLocalizationsFr();
|
||||||
case 'hr':
|
case 'hr':
|
||||||
return AppLocalizationsHr();
|
return AppLocalizationsHr();
|
||||||
|
case 'it':
|
||||||
|
return AppLocalizationsIt();
|
||||||
case 'sl':
|
case 'sl':
|
||||||
return AppLocalizationsSl();
|
return AppLocalizationsSl();
|
||||||
}
|
}
|
||||||
|
|||||||
1241
lib/l10n/app_localizations_de.dart
Normal file
1241
lib/l10n/app_localizations_de.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1104,4 +1104,125 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get offlineLayers => 'Offline Layers';
|
String get offlineLayers => 'Offline Layers';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get locationTrail => 'Location Trail';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showTrailOnMap => 'Show Trail on Map';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailVisible => 'Trail is visible on the map';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailHiddenRecording => 'Trail is hidden (still recording)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get duration => 'Duration';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get points => 'Points';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrail => 'Clear Trail';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrailQuestion => 'Clear Trail?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrailConfirmation =>
|
||||||
|
'Are you sure you want to clear the current location trail? This action cannot be undone.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noTrailRecorded => 'No trail recorded yet';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startTrackingToRecord =>
|
||||||
|
'Start location tracking to record your trail';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailControls => 'Trail Controls';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deviceInformation => 'Device Information';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get bleName => 'BLE Name';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get meshName => 'Mesh Name';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get notSet => 'Not set';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get model => 'Model';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get version => 'Version';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buildDate => 'Build Date';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get firmware => 'Firmware';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxContacts => 'Max Contacts';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxChannels => 'Max Channels';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get publicInfo => 'Public Info';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get meshNetworkName => 'Mesh Network Name';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get nameBroadcastInMesh => 'Name broadcast in mesh advertisements';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get telemetryAndLocationSharing => 'Telemetry & Location Sharing';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lat => 'Lat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lon => 'Lon';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get useCurrentLocation => 'Use current location';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noneUnknown => 'None/Unknown';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatNode => 'Chat Node';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater => 'Repeater';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get roomChannel => 'Room/Channel';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String typeNumber(int number) {
|
||||||
|
return 'Type $number';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String copiedToClipboardShort(String label) {
|
||||||
|
return 'Copied $label to clipboard';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String failedToSave(String error) {
|
||||||
|
return 'Failed to save: $error';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String failedToGetLocation(String error) {
|
||||||
|
return 'Failed to get location: $error';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1236
lib/l10n/app_localizations_es.dart
Normal file
1236
lib/l10n/app_localizations_es.dart
Normal file
File diff suppressed because it is too large
Load Diff
1243
lib/l10n/app_localizations_fr.dart
Normal file
1243
lib/l10n/app_localizations_fr.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1105,4 +1105,125 @@ class AppLocalizationsHr extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get offlineLayers => 'Offline slojevi';
|
String get offlineLayers => 'Offline slojevi';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get locationTrail => 'Putanja lokacije';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showTrailOnMap => 'Prikaži putanju na karti';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailVisible => 'Putanja je vidljiva na karti';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailHiddenRecording => 'Putanja je skrivena (još se snima)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get duration => 'Trajanje';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get points => 'Točke';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrail => 'Obriši putanju';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrailQuestion => 'Obrisati putanju?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrailConfirmation =>
|
||||||
|
'Jeste li sigurni da želite obrisati trenutnu putanju lokacije? Ova radnja se ne može poništiti.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noTrailRecorded => 'Još nije snimljena putanja';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startTrackingToRecord =>
|
||||||
|
'Pokrenite praćenje lokacije za snimanje putanje';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailControls => 'Upravljanje putanjom';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deviceInformation => 'Informacije o uređaju';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get bleName => 'BLE naziv';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get meshName => 'Mesh naziv';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get notSet => 'Nije postavljeno';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get model => 'Model';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get version => 'Verzija';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buildDate => 'Datum izgradnje';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get firmware => 'Firmware';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxContacts => 'Maks. kontakata';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxChannels => 'Maks. kanala';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get publicInfo => 'Javne informacije';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get meshNetworkName => 'Naziv mesh mreže';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get nameBroadcastInMesh => 'Naziv koji se emitira u mesh oglasima';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get telemetryAndLocationSharing => 'Telemetrija i dijeljenje lokacije';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lat => 'Šir';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lon => 'Dug';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get useCurrentLocation => 'Koristi trenutnu lokaciju';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noneUnknown => 'Nema/Nepoznato';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatNode => 'Čvorište za razgovor';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater => 'Repetitor';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get roomChannel => 'Soba/Kanal';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String typeNumber(int number) {
|
||||||
|
return 'Tip $number';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String copiedToClipboardShort(String label) {
|
||||||
|
return 'Kopirano $label u međuspremnik';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String failedToSave(String error) {
|
||||||
|
return 'Neuspjelo spremanje: $error';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String failedToGetLocation(String error) {
|
||||||
|
return 'Neuspjelo dohvaćanje lokacije: $error';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1239
lib/l10n/app_localizations_it.dart
Normal file
1239
lib/l10n/app_localizations_it.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1108,4 +1108,125 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get offlineLayers => 'Brezpovezne plasti';
|
String get offlineLayers => 'Brezpovezne plasti';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get locationTrail => 'Sledilna pot';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showTrailOnMap => 'Prikaži pot na zemljevidu';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailVisible => 'Pot je vidna na zemljevidu';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailHiddenRecording => 'Pot je skrita (še se snema)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get duration => 'Trajanje';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get points => 'Točke';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrail => 'Počisti pot';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrailQuestion => 'Počisti pot?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get clearTrailConfirmation =>
|
||||||
|
'Ste prepričani, da želite počistiti trenutno sledilno pot? Tega dejanja ni mogoče razveljaviti.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noTrailRecorded => 'Še ni posnete poti';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startTrackingToRecord =>
|
||||||
|
'Začnite sledenje lokacije za snemanje poti';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get trailControls => 'Nadzor poti';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deviceInformation => 'Informacije o napravi';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get bleName => 'BLE ime';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get meshName => 'Mesh ime';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get notSet => 'Ni nastavljeno';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get model => 'Model';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get version => 'Različica';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buildDate => 'Datum izdelave';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get firmware => 'Vdelana programska oprema';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxContacts => 'Maks. stikov';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get maxChannels => 'Maks. kanalov';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get publicInfo => 'Javne informacije';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get meshNetworkName => 'Ime mesh omrežja';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get nameBroadcastInMesh => 'Ime, ki se oddaja v mesh oglasih';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get telemetryAndLocationSharing => 'Telemetrija in deljenje lokacije';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lat => 'Šir';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get lon => 'Dol';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get useCurrentLocation => 'Uporabi trenutno lokacijo';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noneUnknown => 'Brez/Neznano';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatNode => 'Vozlišče za klepet';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get repeater => 'Ojačevalnik';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get roomChannel => 'Soba/Kanal';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String typeNumber(int number) {
|
||||||
|
return 'Tip $number';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String copiedToClipboardShort(String label) {
|
||||||
|
return 'Kopirano $label v odložišče';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String failedToSave(String error) {
|
||||||
|
return 'Shranjevanje ni uspelo: $error';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String failedToGetLocation(String error) {
|
||||||
|
return 'Pridobivanje lokacije ni uspelo: $error';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -632,5 +632,81 @@
|
|||||||
|
|
||||||
"onlineLayers": "Spletne plasti",
|
"onlineLayers": "Spletne plasti",
|
||||||
|
|
||||||
"offlineLayers": "Brezpovezne plasti"
|
"offlineLayers": "Brezpovezne plasti",
|
||||||
|
|
||||||
|
"locationTrail": "Sledilna pot",
|
||||||
|
|
||||||
|
"showTrailOnMap": "Prikaži pot na zemljevidu",
|
||||||
|
|
||||||
|
"trailVisible": "Pot je vidna na zemljevidu",
|
||||||
|
|
||||||
|
"trailHiddenRecording": "Pot je skrita (še se snema)",
|
||||||
|
|
||||||
|
"distance": "Razdalja",
|
||||||
|
|
||||||
|
"duration": "Trajanje",
|
||||||
|
|
||||||
|
"points": "Točke",
|
||||||
|
|
||||||
|
"clearTrail": "Počisti pot",
|
||||||
|
|
||||||
|
"clearTrailQuestion": "Počisti pot?",
|
||||||
|
|
||||||
|
"clearTrailConfirmation": "Ste prepričani, da želite počistiti trenutno sledilno pot? Tega dejanja ni mogoče razveljaviti.",
|
||||||
|
|
||||||
|
"noTrailRecorded": "Še ni posnete poti",
|
||||||
|
|
||||||
|
"startTrackingToRecord": "Začnite sledenje lokacije za snemanje poti",
|
||||||
|
|
||||||
|
"trailControls": "Nadzor poti",
|
||||||
|
|
||||||
|
"deviceInformation": "Informacije o napravi",
|
||||||
|
|
||||||
|
"bleName": "BLE ime",
|
||||||
|
|
||||||
|
"meshName": "Mesh ime",
|
||||||
|
|
||||||
|
"notSet": "Ni nastavljeno",
|
||||||
|
|
||||||
|
"model": "Model",
|
||||||
|
|
||||||
|
"version": "Različica",
|
||||||
|
|
||||||
|
"buildDate": "Datum izdelave",
|
||||||
|
|
||||||
|
"firmware": "Vdelana programska oprema",
|
||||||
|
|
||||||
|
"maxContacts": "Maks. stikov",
|
||||||
|
|
||||||
|
"maxChannels": "Maks. kanalov",
|
||||||
|
|
||||||
|
"publicInfo": "Javne informacije",
|
||||||
|
|
||||||
|
"meshNetworkName": "Ime mesh omrežja",
|
||||||
|
|
||||||
|
"nameBroadcastInMesh": "Ime, ki se oddaja v mesh oglasih",
|
||||||
|
|
||||||
|
"telemetryAndLocationSharing": "Telemetrija in deljenje lokacije",
|
||||||
|
|
||||||
|
"lat": "Šir",
|
||||||
|
|
||||||
|
"lon": "Dol",
|
||||||
|
|
||||||
|
"useCurrentLocation": "Uporabi trenutno lokacijo",
|
||||||
|
|
||||||
|
"noneUnknown": "Brez/Neznano",
|
||||||
|
|
||||||
|
"chatNode": "Vozlišče za klepet",
|
||||||
|
|
||||||
|
"repeater": "Ojačevalnik",
|
||||||
|
|
||||||
|
"roomChannel": "Soba/Kanal",
|
||||||
|
|
||||||
|
"typeNumber": "Tip {number}",
|
||||||
|
|
||||||
|
"copiedToClipboardShort": "Kopirano {label} v odložišče",
|
||||||
|
|
||||||
|
"failedToSave": "Shranjevanje ni uspelo: {error}",
|
||||||
|
|
||||||
|
"failedToGetLocation": "Pridobivanje lokacije ni uspelo: {error}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Failed to save: $e'),
|
content: Text(AppLocalizations.of(context)!.failedToSave(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -282,7 +282,7 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Failed to save: $e'),
|
content: Text(AppLocalizations.of(context)!.failedToSave(e.toString())),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -367,7 +367,7 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(
|
||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text('Failed to get location: $e')));
|
).showSnackBar(SnackBar(content: Text(AppLocalizations.of(context)!.failedToGetLocation(e.toString()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,35 +446,35 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Device Information',
|
AppLocalizations.of(context)!.deviceInformation,
|
||||||
style: theme.textTheme.titleLarge?.copyWith(
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_InfoRow('BLE Name', deviceInfo.deviceName ?? 'Unknown'),
|
_InfoRow(AppLocalizations.of(context)!.bleName, deviceInfo.deviceName ?? AppLocalizations.of(context)!.unknown),
|
||||||
_InfoRow('Mesh Name', deviceInfo.selfName ?? 'Not set'),
|
_InfoRow(AppLocalizations.of(context)!.meshName, deviceInfo.selfName ?? AppLocalizations.of(context)!.notSet),
|
||||||
_InfoRow('Type', _getDeviceTypeString(deviceInfo.deviceType)),
|
_InfoRow(AppLocalizations.of(context)!.type, _getDeviceTypeString(context, deviceInfo.deviceType)),
|
||||||
_InfoRow('Model', deviceInfo.manufacturerModel ?? 'Unknown'),
|
_InfoRow(AppLocalizations.of(context)!.model, deviceInfo.manufacturerModel ?? AppLocalizations.of(context)!.unknown),
|
||||||
_InfoRow('Version', deviceInfo.semanticVersion ?? 'Unknown'),
|
_InfoRow(AppLocalizations.of(context)!.version, deviceInfo.semanticVersion ?? AppLocalizations.of(context)!.unknown),
|
||||||
_InfoRow(
|
_InfoRow(
|
||||||
'Build Date',
|
AppLocalizations.of(context)!.buildDate,
|
||||||
deviceInfo.firmwareBuildDate ?? 'Unknown',
|
deviceInfo.firmwareBuildDate ?? AppLocalizations.of(context)!.unknown,
|
||||||
),
|
),
|
||||||
_InfoRow(
|
_InfoRow(
|
||||||
'Firmware',
|
AppLocalizations.of(context)!.firmware,
|
||||||
'v${deviceInfo.firmwareVersion?.toString() ?? "?"}',
|
'v${deviceInfo.firmwareVersion?.toString() ?? "?"}',
|
||||||
),
|
),
|
||||||
_InfoRow(
|
_InfoRow(
|
||||||
'Max Contacts',
|
AppLocalizations.of(context)!.maxContacts,
|
||||||
deviceInfo.maxContacts?.toString() ?? 'Unknown',
|
deviceInfo.maxContacts?.toString() ?? AppLocalizations.of(context)!.unknown,
|
||||||
),
|
),
|
||||||
_InfoRow(
|
_InfoRow(
|
||||||
'Max Channels',
|
AppLocalizations.of(context)!.maxChannels,
|
||||||
deviceInfo.maxChannels?.toString() ?? 'Unknown',
|
deviceInfo.maxChannels?.toString() ?? AppLocalizations.of(context)!.unknown,
|
||||||
),
|
),
|
||||||
_CopyableInfoRow(
|
_CopyableInfoRow(
|
||||||
'Public Key',
|
AppLocalizations.of(context)!.publicKey,
|
||||||
_getPublicKeyHex(deviceInfo.publicKey),
|
_getPublicKeyHex(deviceInfo.publicKey),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -495,7 +495,7 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Public Info',
|
AppLocalizations.of(context)!.publicInfo,
|
||||||
style: theme.textTheme.titleLarge?.copyWith(
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -518,10 +518,10 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
// Mesh Network Name
|
// Mesh Network Name
|
||||||
TextField(
|
TextField(
|
||||||
controller: _nameController,
|
controller: _nameController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Mesh Network Name',
|
labelText: AppLocalizations.of(context)!.meshNetworkName,
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
helperText: 'Name broadcast in mesh advertisements',
|
helperText: AppLocalizations.of(context)!.nameBroadcastInMesh,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -531,7 +531,7 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Telemetry & Location Sharing',
|
AppLocalizations.of(context)!.telemetryAndLocationSharing,
|
||||||
style: theme.textTheme.bodyMedium,
|
style: theme.textTheme.bodyMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -554,9 +554,9 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _latController,
|
controller: _latController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Lat',
|
labelText: AppLocalizations.of(context)!.lat,
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
),
|
),
|
||||||
keyboardType: const TextInputType.numberWithOptions(
|
keyboardType: const TextInputType.numberWithOptions(
|
||||||
@@ -569,9 +569,9 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _lonController,
|
controller: _lonController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Lon',
|
labelText: AppLocalizations.of(context)!.lon,
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
),
|
),
|
||||||
keyboardType: const TextInputType.numberWithOptions(
|
keyboardType: const TextInputType.numberWithOptions(
|
||||||
@@ -584,7 +584,7 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
IconButton.filled(
|
IconButton.filled(
|
||||||
onPressed: _useCurrentLocation,
|
onPressed: _useCurrentLocation,
|
||||||
icon: const Icon(Icons.my_location, size: 20),
|
icon: const Icon(Icons.my_location, size: 20),
|
||||||
tooltip: 'Use current location',
|
tooltip: AppLocalizations.of(context)!.useCurrentLocation,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -729,19 +729,19 @@ class _DeviceConfigScreenState extends State<DeviceConfigScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getDeviceTypeString(int? deviceType) {
|
String _getDeviceTypeString(BuildContext context, int? deviceType) {
|
||||||
if (deviceType == null) return 'Unknown';
|
if (deviceType == null) return AppLocalizations.of(context)!.unknown;
|
||||||
switch (deviceType) {
|
switch (deviceType) {
|
||||||
case 0:
|
case 0:
|
||||||
return 'None/Unknown';
|
return AppLocalizations.of(context)!.noneUnknown;
|
||||||
case 1:
|
case 1:
|
||||||
return 'Chat Node';
|
return AppLocalizations.of(context)!.chatNode;
|
||||||
case 2:
|
case 2:
|
||||||
return 'Repeater';
|
return AppLocalizations.of(context)!.repeater;
|
||||||
case 3:
|
case 3:
|
||||||
return 'Room/Channel';
|
return AppLocalizations.of(context)!.roomChannel;
|
||||||
default:
|
default:
|
||||||
return 'Type $deviceType';
|
return AppLocalizations.of(context)!.typeNumber(deviceType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +815,7 @@ class _CopyableInfoRow extends StatelessWidget {
|
|||||||
Clipboard.setData(ClipboardData(text: value));
|
Clipboard.setData(ClipboardData(text: value));
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Copied $label to clipboard'),
|
content: Text(AppLocalizations.of(context)!.copiedToClipboardShort(label)),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1353,9 +1353,6 @@ class _MapTabState extends State<MapTab> with AutomaticKeepAliveClientMixin {
|
|||||||
objectCount: messagesProvider.objectMarkers.length,
|
objectCount: messagesProvider.objectMarkers.length,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Trail stats overlay (top-left, below legend if shown)
|
|
||||||
if (!_isFullscreen)
|
|
||||||
const TrailStatsOverlay(),
|
|
||||||
// Map controls - right side (hidden in fullscreen mode)
|
// Map controls - right side (hidden in fullscreen mode)
|
||||||
if (!_isFullscreen)
|
if (!_isFullscreen)
|
||||||
Positioned(
|
Positioned(
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ class BleResponseHandler {
|
|||||||
void _handleContact(BufferReader reader) {
|
void _handleContact(BufferReader reader) {
|
||||||
try {
|
try {
|
||||||
final contact = FrameParser.parseContact(reader);
|
final contact = FrameParser.parseContact(reader);
|
||||||
print(' ✅ [Contact] Parsed successfully');
|
print(' ✅ [Contact] Parsed successfully: ${contact.advName}');
|
||||||
|
print(' outPathLen: ${contact.outPathLen} (${contact.pathDescription})');
|
||||||
_pendingContacts.add(contact);
|
_pendingContacts.add(contact);
|
||||||
onContactReceived?.call(contact);
|
onContactReceived?.call(contact);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -468,7 +469,8 @@ class BleResponseHandler {
|
|||||||
void _handleNewAdvert(BufferReader reader) {
|
void _handleNewAdvert(BufferReader reader) {
|
||||||
try {
|
try {
|
||||||
final contact = FrameParser.parseContact(reader);
|
final contact = FrameParser.parseContact(reader);
|
||||||
print(' ✅ [NewAdvert] Parsed successfully');
|
print(' ✅ [NewAdvert] Parsed successfully: ${contact.advName}');
|
||||||
|
print(' outPathLen: ${contact.outPathLen} (${contact.pathDescription})');
|
||||||
onContactReceived?.call(contact);
|
onContactReceived?.call(contact);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(' ❌ [NewAdvert] Parsing error: $e');
|
print(' ❌ [NewAdvert] Parsing error: $e');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../../providers/map_provider.dart';
|
import '../../providers/map_provider.dart';
|
||||||
|
import '../../l10n/app_localizations.dart';
|
||||||
|
|
||||||
/// Trail management controls widget
|
/// Trail management controls widget
|
||||||
class TrailControls extends StatelessWidget {
|
class TrailControls extends StatelessWidget {
|
||||||
@@ -8,31 +9,52 @@ class TrailControls extends StatelessWidget {
|
|||||||
|
|
||||||
void _showTrailMenu(BuildContext context) {
|
void _showTrailMenu(BuildContext context) {
|
||||||
final mapProvider = Provider.of<MapProvider>(context, listen: false);
|
final mapProvider = Provider.of<MapProvider>(context, listen: false);
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => Container(
|
isScrollControlled: true,
|
||||||
padding: const EdgeInsets.all(16),
|
builder: (context) => StatefulBuilder(
|
||||||
child: Column(
|
builder: (context, setModalState) => Container(
|
||||||
mainAxisSize: MainAxisSize.min,
|
padding: const EdgeInsets.all(16),
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
child: Column(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.timeline, size: 24),
|
Row(
|
||||||
const SizedBox(width: 12),
|
children: [
|
||||||
const Text(
|
const Icon(Icons.timeline, size: 24),
|
||||||
'Location Trail',
|
const SizedBox(width: 12),
|
||||||
style: TextStyle(
|
Text(
|
||||||
fontSize: 20,
|
l10n.locationTrail,
|
||||||
fontWeight: FontWeight.bold,
|
style: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
|
||||||
|
|
||||||
// Trail stats
|
// Trail visibility toggle
|
||||||
|
SwitchListTile(
|
||||||
|
secondary: const Icon(Icons.visibility),
|
||||||
|
title: Text(l10n.showTrailOnMap),
|
||||||
|
subtitle: Text(
|
||||||
|
mapProvider.isTrailVisible
|
||||||
|
? l10n.trailVisible
|
||||||
|
: l10n.trailHiddenRecording,
|
||||||
|
),
|
||||||
|
value: mapProvider.isTrailVisible,
|
||||||
|
onChanged: (value) {
|
||||||
|
mapProvider.toggleTrailVisibility();
|
||||||
|
setModalState(() {}); // Update modal UI
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
|
// Trail stats
|
||||||
if (mapProvider.currentTrail != null && mapProvider.currentTrail!.points.isNotEmpty)
|
if (mapProvider.currentTrail != null && mapProvider.currentTrail!.points.isNotEmpty)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
@@ -46,19 +68,19 @@ class TrailControls extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
_buildStatRow(
|
_buildStatRow(
|
||||||
icon: Icons.straighten,
|
icon: Icons.straighten,
|
||||||
label: 'Distance',
|
label: l10n.distance,
|
||||||
value: _formatDistance(mapProvider.totalTrailDistance),
|
value: _formatDistance(mapProvider.totalTrailDistance),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_buildStatRow(
|
_buildStatRow(
|
||||||
icon: Icons.access_time,
|
icon: Icons.access_time,
|
||||||
label: 'Duration',
|
label: l10n.duration,
|
||||||
value: _formatDuration(mapProvider.trailDuration),
|
value: _formatDuration(mapProvider.trailDuration),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_buildStatRow(
|
_buildStatRow(
|
||||||
icon: Icons.place,
|
icon: Icons.place,
|
||||||
label: 'Points',
|
label: l10n.points,
|
||||||
value: '${mapProvider.currentTrail!.points.length}',
|
value: '${mapProvider.currentTrail!.points.length}',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -71,10 +93,10 @@ class TrailControls extends StatelessWidget {
|
|||||||
if (mapProvider.currentTrail != null && mapProvider.currentTrail!.points.isNotEmpty)
|
if (mapProvider.currentTrail != null && mapProvider.currentTrail!.points.isNotEmpty)
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_showClearConfirmation(context, mapProvider);
|
_showClearConfirmation(context, mapProvider, l10n);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.delete_outline),
|
icon: const Icon(Icons.delete_outline),
|
||||||
label: const Text('Clear Trail'),
|
label: Text(l10n.clearTrail),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
@@ -84,24 +106,24 @@ class TrailControls extends StatelessWidget {
|
|||||||
|
|
||||||
// No trail message
|
// No trail message
|
||||||
if (mapProvider.currentTrail == null || mapProvider.currentTrail!.points.isEmpty)
|
if (mapProvider.currentTrail == null || mapProvider.currentTrail!.points.isEmpty)
|
||||||
const Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.timeline, size: 48, color: Colors.grey),
|
const Icon(Icons.timeline, size: 48, color: Colors.grey),
|
||||||
SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'No trail recorded yet',
|
l10n.noTrailRecorded,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'Start location tracking to record your trail',
|
l10n.startTrackingToRecord,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
@@ -115,28 +137,27 @@ class TrailControls extends StatelessWidget {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
// Close button
|
// Close button
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: const Text('Close'),
|
child: Text(l10n.close),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showClearConfirmation(BuildContext context, MapProvider mapProvider) {
|
void _showClearConfirmation(BuildContext context, MapProvider mapProvider, AppLocalizations l10n) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Clear Trail?'),
|
title: Text(l10n.clearTrailQuestion),
|
||||||
content: const Text(
|
content: Text(l10n.clearTrailConfirmation),
|
||||||
'Are you sure you want to clear the current location trail? This action cannot be undone.',
|
|
||||||
),
|
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: const Text('Cancel'),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -145,7 +166,7 @@ class TrailControls extends StatelessWidget {
|
|||||||
Navigator.pop(context); // Close bottom sheet
|
Navigator.pop(context); // Close bottom sheet
|
||||||
},
|
},
|
||||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||||
child: const Text('Clear'),
|
child: Text(l10n.clearTrail),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -204,9 +225,10 @@ class TrailControls extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return FloatingActionButton.small(
|
return FloatingActionButton.small(
|
||||||
heroTag: 'trail_controls',
|
heroTag: 'trail_controls',
|
||||||
tooltip: 'Trail Controls',
|
tooltip: l10n.trailControls,
|
||||||
onPressed: () => _showTrailMenu(context),
|
onPressed: () => _showTrailMenu(context),
|
||||||
child: const Icon(Icons.timeline),
|
child: const Icon(Icons.timeline),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user