mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-10-11 10:18:42 +02:00
require profile selection
This commit is contained in:
1 parent
c7f4164f12
commit
2a7004e5a2
13 files changed
+103
-41
No files matched your search
@@ -1,7 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
"1.2.8": {
|
||||||
|
"content": "• UX: Profile selection is now a required step to prevent accidental submission of default profile.\n• NEW: Note in welcome message about not submitting data you cannot vouch for personally (no street view etc)\n• NEW: Added default operator profiles for the most common private operators nationwide (Lowe's, Home Depot, et al)"
|
||||||
|
},
|
||||||
"1.2.7": {
|
"1.2.7": {
|
||||||
"content": "• NEW: Compass indicator shows map orientation; tap to spin north-up\n• Smart area caching: Loads 3x larger areas and refreshes data every 60 seconds for much faster browsing\n• Enhanced tile loading: Increased retry attempts with faster delays - tiles load much more reliably\n• Better network status: Simplified loading indicator logic\n• Instant node display: Surveillance devices now appear immediately when data finishes loading\n• Node limit alerts: Get notified when some nodes are not drawn"
|
"content": "• NEW: Compass indicator shows map orientation; tap to spin north-up\n• Smart area caching: Loads 3x larger areas and refreshes data every 60 seconds for much faster browsing\n• Enhanced tile loading: Increased retry attempts with faster delays - tiles load much more reliably\n• Better network status: Simplified loading indicator logic\n• Instant node display: Surveillance devices now appear immediately when data finishes loading\n• Node limit alerts: Get notified when some nodes are not drawn"
|
||||||
},
|
},
|
||||||
"1.2.4": {
|
"1.2.4": {
|
||||||
"content": "• New welcome popup for first-time users with essential privacy information\n• Automatic changelog display when app updates (like this one!)\n• Added Release Notes viewer in Settings > About\n• Enhanced user onboarding and transparency about data handling\n• Improved documentation for contributors"
|
"content": "• New welcome popup for first-time users with essential privacy information\n• Automatic changelog display when app updates (like this one!)\n• Added Release Notes viewer in Settings > About\n• Enhanced user onboarding and transparency about data handling\n• Improved documentation for contributors"
|
||||||
},
|
},
|
||||||
@@ -11,9 +14,6 @@
|
|||||||
"1.2.2": {
|
"1.2.2": {
|
||||||
"content": "• New surveillance device profiles added\n• Improved tile loading performance\n• Fixed issue with GPS accuracy\n• Updated translations"
|
"content": "• New surveillance device profiles added\n• Improved tile loading performance\n• Fixed issue with GPS accuracy\n• Updated translations"
|
||||||
},
|
},
|
||||||
"1.2.1": {
|
|
||||||
"content": ""
|
|
||||||
},
|
|
||||||
"1.2.0": {
|
"1.2.0": {
|
||||||
"content": "• Major UI improvements\n• Added proximity alerts\n• Enhanced offline capabilities\n• New suspected locations feature"
|
"content": "• Major UI improvements\n• Added proximity alerts\n• Enhanced offline capabilities\n• New suspected locations feature"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
|
"selectProfile": "Profil auswählen...",
|
||||||
|
"profileRequired": "Bitte wählen Sie ein Profil aus, um fortzufahren.",
|
||||||
"direction": "Richtung {}°",
|
"direction": "Richtung {}°",
|
||||||
"profileNoDirectionInfo": "Dieses Profil benötigt keine Richtung.",
|
"profileNoDirectionInfo": "Dieses Profil benötigt keine Richtung.",
|
||||||
"mustBeLoggedIn": "Sie müssen angemeldet sein, um neue Knoten zu übertragen. Bitte melden Sie sich über die Einstellungen an.",
|
"mustBeLoggedIn": "Sie müssen angemeldet sein, um neue Knoten zu übertragen. Bitte melden Sie sich über die Einstellungen an.",
|
||||||
@@ -83,6 +85,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "Knoten #{} Bearbeiten",
|
"title": "Knoten #{} Bearbeiten",
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
|
"selectProfile": "Profil auswählen...",
|
||||||
|
"profileRequired": "Bitte wählen Sie ein Profil aus, um fortzufahren.",
|
||||||
"direction": "Richtung {}°",
|
"direction": "Richtung {}°",
|
||||||
"profileNoDirectionInfo": "Dieses Profil benötigt keine Richtung.",
|
"profileNoDirectionInfo": "Dieses Profil benötigt keine Richtung.",
|
||||||
"mustBeLoggedIn": "Sie müssen angemeldet sein, um Knoten zu bearbeiten. Bitte melden Sie sich über die Einstellungen an.",
|
"mustBeLoggedIn": "Sie müssen angemeldet sein, um Knoten zu bearbeiten. Bitte melden Sie sich über die Einstellungen an.",
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "Profile",
|
"profile": "Profile",
|
||||||
|
"selectProfile": "Select a profile...",
|
||||||
|
"profileRequired": "Please select a profile to continue.",
|
||||||
"direction": "Direction {}°",
|
"direction": "Direction {}°",
|
||||||
"profileNoDirectionInfo": "This profile does not require a direction.",
|
"profileNoDirectionInfo": "This profile does not require a direction.",
|
||||||
"mustBeLoggedIn": "You must be logged in to submit new nodes. Please log in via Settings.",
|
"mustBeLoggedIn": "You must be logged in to submit new nodes. Please log in via Settings.",
|
||||||
@@ -100,6 +102,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "Edit Node #{}",
|
"title": "Edit Node #{}",
|
||||||
"profile": "Profile",
|
"profile": "Profile",
|
||||||
|
"selectProfile": "Select a profile...",
|
||||||
|
"profileRequired": "Please select a profile to continue.",
|
||||||
"direction": "Direction {}°",
|
"direction": "Direction {}°",
|
||||||
"profileNoDirectionInfo": "This profile does not require a direction.",
|
"profileNoDirectionInfo": "This profile does not require a direction.",
|
||||||
"mustBeLoggedIn": "You must be logged in to edit nodes. Please log in via Settings.",
|
"mustBeLoggedIn": "You must be logged in to edit nodes. Please log in via Settings.",
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "Perfil",
|
"profile": "Perfil",
|
||||||
|
"selectProfile": "Seleccionar un perfil...",
|
||||||
|
"profileRequired": "Por favor, seleccione un perfil para continuar.",
|
||||||
"direction": "Dirección {}°",
|
"direction": "Dirección {}°",
|
||||||
"profileNoDirectionInfo": "Este perfil no requiere una dirección.",
|
"profileNoDirectionInfo": "Este perfil no requiere una dirección.",
|
||||||
"mustBeLoggedIn": "Debe estar conectado para enviar nuevos nodos. Por favor, inicie sesión a través de Configuración.",
|
"mustBeLoggedIn": "Debe estar conectado para enviar nuevos nodos. Por favor, inicie sesión a través de Configuración.",
|
||||||
@@ -100,6 +102,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "Editar Nodo #{}",
|
"title": "Editar Nodo #{}",
|
||||||
"profile": "Perfil",
|
"profile": "Perfil",
|
||||||
|
"selectProfile": "Seleccionar un perfil...",
|
||||||
|
"profileRequired": "Por favor, seleccione un perfil para continuar.",
|
||||||
"direction": "Dirección {}°",
|
"direction": "Dirección {}°",
|
||||||
"profileNoDirectionInfo": "Este perfil no requiere una dirección.",
|
"profileNoDirectionInfo": "Este perfil no requiere una dirección.",
|
||||||
"mustBeLoggedIn": "Debe estar conectado para editar nodos. Por favor, inicie sesión a través de Configuración.",
|
"mustBeLoggedIn": "Debe estar conectado para editar nodos. Por favor, inicie sesión a través de Configuración.",
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
|
"selectProfile": "Sélectionner un profil...",
|
||||||
|
"profileRequired": "Veuillez sélectionner un profil pour continuer.",
|
||||||
"direction": "Direction {}°",
|
"direction": "Direction {}°",
|
||||||
"profileNoDirectionInfo": "Ce profil ne nécessite pas de direction.",
|
"profileNoDirectionInfo": "Ce profil ne nécessite pas de direction.",
|
||||||
"mustBeLoggedIn": "Vous devez être connecté pour soumettre de nouveaux nœuds. Veuillez vous connecter via les Paramètres.",
|
"mustBeLoggedIn": "Vous devez être connecté pour soumettre de nouveaux nœuds. Veuillez vous connecter via les Paramètres.",
|
||||||
@@ -100,6 +102,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "Modifier Nœud #{}",
|
"title": "Modifier Nœud #{}",
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
|
"selectProfile": "Sélectionner un profil...",
|
||||||
|
"profileRequired": "Veuillez sélectionner un profil pour continuer.",
|
||||||
"direction": "Direction {}°",
|
"direction": "Direction {}°",
|
||||||
"profileNoDirectionInfo": "Ce profil ne nécessite pas de direction.",
|
"profileNoDirectionInfo": "Ce profil ne nécessite pas de direction.",
|
||||||
"mustBeLoggedIn": "Vous devez être connecté pour modifier les nœuds. Veuillez vous connecter via les Paramètres.",
|
"mustBeLoggedIn": "Vous devez être connecté pour modifier les nœuds. Veuillez vous connecter via les Paramètres.",
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "Profilo",
|
"profile": "Profilo",
|
||||||
|
"selectProfile": "Seleziona un profilo...",
|
||||||
|
"profileRequired": "Per favore seleziona un profilo per continuare.",
|
||||||
"direction": "Direzione {}°",
|
"direction": "Direzione {}°",
|
||||||
"profileNoDirectionInfo": "Questo profilo non richiede una direzione.",
|
"profileNoDirectionInfo": "Questo profilo non richiede una direzione.",
|
||||||
"mustBeLoggedIn": "Devi essere loggato per inviare nuovi nodi. Per favore accedi tramite Impostazioni.",
|
"mustBeLoggedIn": "Devi essere loggato per inviare nuovi nodi. Per favore accedi tramite Impostazioni.",
|
||||||
@@ -100,6 +102,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "Modifica Nodo #{}",
|
"title": "Modifica Nodo #{}",
|
||||||
"profile": "Profilo",
|
"profile": "Profilo",
|
||||||
|
"selectProfile": "Seleziona un profilo...",
|
||||||
|
"profileRequired": "Per favore seleziona un profilo per continuare.",
|
||||||
"direction": "Direzione {}°",
|
"direction": "Direzione {}°",
|
||||||
"profileNoDirectionInfo": "Questo profilo non richiede una direzione.",
|
"profileNoDirectionInfo": "Questo profilo non richiede una direzione.",
|
||||||
"mustBeLoggedIn": "Devi essere loggato per modificare i nodi. Per favore accedi tramite Impostazioni.",
|
"mustBeLoggedIn": "Devi essere loggato per modificare i nodi. Per favore accedi tramite Impostazioni.",
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "Perfil",
|
"profile": "Perfil",
|
||||||
|
"selectProfile": "Selecionar um perfil...",
|
||||||
|
"profileRequired": "Por favor, selecione um perfil para continuar.",
|
||||||
"direction": "Direção {}°",
|
"direction": "Direção {}°",
|
||||||
"profileNoDirectionInfo": "Este perfil não requer uma direção.",
|
"profileNoDirectionInfo": "Este perfil não requer uma direção.",
|
||||||
"mustBeLoggedIn": "Você deve estar logado para enviar novos nós. Por favor, faça login via Configurações.",
|
"mustBeLoggedIn": "Você deve estar logado para enviar novos nós. Por favor, faça login via Configurações.",
|
||||||
@@ -100,6 +102,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "Editar Nó #{}",
|
"title": "Editar Nó #{}",
|
||||||
"profile": "Perfil",
|
"profile": "Perfil",
|
||||||
|
"selectProfile": "Selecionar um perfil...",
|
||||||
|
"profileRequired": "Por favor, selecione um perfil para continuar.",
|
||||||
"direction": "Direção {}°",
|
"direction": "Direção {}°",
|
||||||
"profileNoDirectionInfo": "Este perfil não requer uma direção.",
|
"profileNoDirectionInfo": "Este perfil não requer uma direção.",
|
||||||
"mustBeLoggedIn": "Você deve estar logado para editar nós. Por favor, faça login via Configurações.",
|
"mustBeLoggedIn": "Você deve estar logado para editar nós. Por favor, faça login via Configurações.",
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
},
|
},
|
||||||
"addNode": {
|
"addNode": {
|
||||||
"profile": "配置文件",
|
"profile": "配置文件",
|
||||||
|
"selectProfile": "选择配置文件...",
|
||||||
|
"profileRequired": "请选择配置文件以继续。",
|
||||||
"direction": "方向 {}°",
|
"direction": "方向 {}°",
|
||||||
"profileNoDirectionInfo": "此配置文件不需要方向。",
|
"profileNoDirectionInfo": "此配置文件不需要方向。",
|
||||||
"mustBeLoggedIn": "您必须登录才能提交新节点。请通过设置登录。",
|
"mustBeLoggedIn": "您必须登录才能提交新节点。请通过设置登录。",
|
||||||
@@ -100,6 +102,8 @@
|
|||||||
"editNode": {
|
"editNode": {
|
||||||
"title": "编辑节点 #{}",
|
"title": "编辑节点 #{}",
|
||||||
"profile": "配置文件",
|
"profile": "配置文件",
|
||||||
|
"selectProfile": "选择配置文件...",
|
||||||
|
"profileRequired": "请选择配置文件以继续。",
|
||||||
"direction": "方向 {}°",
|
"direction": "方向 {}°",
|
||||||
"profileNoDirectionInfo": "此配置文件不需要方向。",
|
"profileNoDirectionInfo": "此配置文件不需要方向。",
|
||||||
"mustBeLoggedIn": "您必须登录才能编辑节点。请通过设置登录。",
|
"mustBeLoggedIn": "您必须登录才能编辑节点。请通过设置登录。",
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import '../models/osm_node.dart';
|
|||||||
|
|
||||||
// ------------------ AddNodeSession ------------------
|
// ------------------ AddNodeSession ------------------
|
||||||
class AddNodeSession {
|
class AddNodeSession {
|
||||||
AddNodeSession({required this.profile, this.directionDegrees = 0});
|
AddNodeSession({this.profile, this.directionDegrees = 0});
|
||||||
NodeProfile profile;
|
NodeProfile? profile;
|
||||||
OperatorProfile? operatorProfile;
|
OperatorProfile? operatorProfile;
|
||||||
double directionDegrees;
|
double directionDegrees;
|
||||||
LatLng? target;
|
LatLng? target;
|
||||||
@@ -18,13 +18,13 @@ class AddNodeSession {
|
|||||||
class EditNodeSession {
|
class EditNodeSession {
|
||||||
EditNodeSession({
|
EditNodeSession({
|
||||||
required this.originalNode,
|
required this.originalNode,
|
||||||
required this.profile,
|
this.profile,
|
||||||
required this.directionDegrees,
|
required this.directionDegrees,
|
||||||
required this.target,
|
required this.target,
|
||||||
});
|
});
|
||||||
|
|
||||||
final OsmNode originalNode; // The original node being edited
|
final OsmNode originalNode; // The original node being edited
|
||||||
NodeProfile profile;
|
NodeProfile? profile;
|
||||||
OperatorProfile? operatorProfile;
|
OperatorProfile? operatorProfile;
|
||||||
double directionDegrees;
|
double directionDegrees;
|
||||||
LatLng target; // Current position (can be dragged)
|
LatLng target; // Current position (can be dragged)
|
||||||
@@ -39,11 +39,8 @@ class SessionState extends ChangeNotifier {
|
|||||||
EditNodeSession? get editSession => _editSession;
|
EditNodeSession? get editSession => _editSession;
|
||||||
|
|
||||||
void startAddSession(List<NodeProfile> enabledProfiles) {
|
void startAddSession(List<NodeProfile> enabledProfiles) {
|
||||||
final submittableProfiles = enabledProfiles.where((p) => p.isSubmittable).toList();
|
// Start with no profile selected - force user to choose
|
||||||
final defaultProfile = submittableProfiles.isNotEmpty
|
_session = AddNodeSession();
|
||||||
? submittableProfiles.first
|
|
||||||
: enabledProfiles.first; // Fallback to any enabled profile
|
|
||||||
_session = AddNodeSession(profile: defaultProfile);
|
|
||||||
_editSession = null; // Clear any edit session
|
_editSession = null; // Clear any edit session
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -52,11 +49,9 @@ class SessionState extends ChangeNotifier {
|
|||||||
final submittableProfiles = enabledProfiles.where((p) => p.isSubmittable).toList();
|
final submittableProfiles = enabledProfiles.where((p) => p.isSubmittable).toList();
|
||||||
|
|
||||||
// Try to find a matching profile based on the node's tags
|
// Try to find a matching profile based on the node's tags
|
||||||
NodeProfile matchingProfile = submittableProfiles.isNotEmpty
|
NodeProfile? matchingProfile;
|
||||||
? submittableProfiles.first
|
|
||||||
: enabledProfiles.first;
|
|
||||||
|
|
||||||
// Attempt to find a better match by comparing tags
|
// Attempt to find a match by comparing tags
|
||||||
for (final profile in submittableProfiles) {
|
for (final profile in submittableProfiles) {
|
||||||
if (_profileMatchesTags(profile, node.tags)) {
|
if (_profileMatchesTags(profile, node.tags)) {
|
||||||
matchingProfile = profile;
|
matchingProfile = profile;
|
||||||
@@ -64,6 +59,7 @@ class SessionState extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start with no profile selected if no match found - force user to choose
|
||||||
_editSession = EditNodeSession(
|
_editSession = EditNodeSession(
|
||||||
originalNode: node,
|
originalNode: node,
|
||||||
profile: matchingProfile,
|
profile: matchingProfile,
|
||||||
@@ -151,7 +147,7 @@ class SessionState extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddNodeSession? commitSession() {
|
AddNodeSession? commitSession() {
|
||||||
if (_session?.target == null) return null;
|
if (_session?.target == null || _session?.profile == null) return null;
|
||||||
|
|
||||||
final session = _session!;
|
final session = _session!;
|
||||||
_session = null;
|
_session = null;
|
||||||
@@ -160,7 +156,7 @@ class SessionState extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EditNodeSession? commitEditSession() {
|
EditNodeSession? commitEditSession() {
|
||||||
if (_editSession == null) return null;
|
if (_editSession?.profile == null) return null;
|
||||||
|
|
||||||
final session = _editSession!;
|
final session = _editSession!;
|
||||||
_editSession = null;
|
_editSession = null;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class UploadQueueState extends ChangeNotifier {
|
|||||||
final upload = PendingUpload(
|
final upload = PendingUpload(
|
||||||
coord: session.target!,
|
coord: session.target!,
|
||||||
direction: session.directionDegrees,
|
direction: session.directionDegrees,
|
||||||
profile: session.profile,
|
profile: session.profile!, // Safe to use ! because commitSession() checks for null
|
||||||
operatorProfile: session.operatorProfile,
|
operatorProfile: session.operatorProfile,
|
||||||
uploadMode: uploadMode,
|
uploadMode: uploadMode,
|
||||||
operation: UploadOperation.create,
|
operation: UploadOperation.create,
|
||||||
@@ -64,7 +64,7 @@ class UploadQueueState extends ChangeNotifier {
|
|||||||
final upload = PendingUpload(
|
final upload = PendingUpload(
|
||||||
coord: session.target,
|
coord: session.target,
|
||||||
direction: session.directionDegrees,
|
direction: session.directionDegrees,
|
||||||
profile: session.profile,
|
profile: session.profile!, // Safe to use ! because commitEditSession() checks for null
|
||||||
operatorProfile: session.operatorProfile,
|
operatorProfile: session.operatorProfile,
|
||||||
uploadMode: uploadMode,
|
uploadMode: uploadMode,
|
||||||
operation: UploadOperation.modify,
|
operation: UploadOperation.modify,
|
||||||
|
|||||||
@@ -34,7 +34,10 @@ class AddNodeSheet extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final submittableProfiles = appState.enabledProfiles.where((p) => p.isSubmittable).toList();
|
final submittableProfiles = appState.enabledProfiles.where((p) => p.isSubmittable).toList();
|
||||||
final allowSubmit = appState.isLoggedIn && submittableProfiles.isNotEmpty && session.profile.isSubmittable;
|
final allowSubmit = appState.isLoggedIn &&
|
||||||
|
submittableProfiles.isNotEmpty &&
|
||||||
|
session.profile != null &&
|
||||||
|
session.profile!.isSubmittable;
|
||||||
|
|
||||||
void _openRefineTags() async {
|
void _openRefineTags() async {
|
||||||
final result = await Navigator.push<OperatorProfile?>(
|
final result = await Navigator.push<OperatorProfile?>(
|
||||||
@@ -66,13 +69,13 @@ class AddNodeSheet extends StatelessWidget {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(locService.t('addNode.profile')),
|
title: Text(locService.t('addNode.profile')),
|
||||||
trailing: DropdownButton<NodeProfile>(
|
trailing: DropdownButton<NodeProfile?>(
|
||||||
value: session.profile,
|
value: session.profile,
|
||||||
|
hint: Text(locService.t('addNode.selectProfile')),
|
||||||
items: submittableProfiles
|
items: submittableProfiles
|
||||||
.map((p) => DropdownMenuItem(value: p, child: Text(p.name)))
|
.map((p) => DropdownMenuItem(value: p, child: Text(p.name)))
|
||||||
.toList(),
|
.toList(),
|
||||||
onChanged: (p) =>
|
onChanged: (p) => appState.updateSession(profile: p),
|
||||||
appState.updateSession(profile: p ?? session.profile),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -83,12 +86,12 @@ class AddNodeSheet extends StatelessWidget {
|
|||||||
divisions: 359,
|
divisions: 359,
|
||||||
value: session.directionDegrees,
|
value: session.directionDegrees,
|
||||||
label: session.directionDegrees.round().toString(),
|
label: session.directionDegrees.round().toString(),
|
||||||
onChanged: session.profile.requiresDirection
|
onChanged: (session.profile != null && session.profile!.requiresDirection)
|
||||||
? (v) => appState.updateSession(directionDeg: v)
|
? (v) => appState.updateSession(directionDeg: v)
|
||||||
: null, // Disables slider when requiresDirection is false
|
: null, // Disabled when no profile selected or profile doesn't require direction
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!session.profile.requiresDirection)
|
if (session.profile != null && !session.profile!.requiresDirection)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -136,7 +139,23 @@ class AddNodeSheet extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else if (!session.profile.isSubmittable)
|
else if (session.profile == null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.info_outline, color: Colors.orange, size: 20),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
locService.t('addNode.profileRequired'),
|
||||||
|
style: const TextStyle(color: Colors.orange, fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else if (!session.profile!.isSubmittable)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -158,7 +177,7 @@ class AddNodeSheet extends StatelessWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
onPressed: _openRefineTags,
|
onPressed: session.profile != null ? _openRefineTags : null, // Disabled when no profile selected
|
||||||
icon: const Icon(Icons.tune),
|
icon: const Icon(Icons.tune),
|
||||||
label: Text(session.operatorProfile != null
|
label: Text(session.operatorProfile != null
|
||||||
? locService.t('addNode.refineTagsWithProfile', params: [session.operatorProfile!.name])
|
? locService.t('addNode.refineTagsWithProfile', params: [session.operatorProfile!.name])
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ class EditNodeSheet extends StatelessWidget {
|
|||||||
|
|
||||||
final submittableProfiles = appState.enabledProfiles.where((p) => p.isSubmittable).toList();
|
final submittableProfiles = appState.enabledProfiles.where((p) => p.isSubmittable).toList();
|
||||||
final isSandboxMode = appState.uploadMode == UploadMode.sandbox;
|
final isSandboxMode = appState.uploadMode == UploadMode.sandbox;
|
||||||
final allowSubmit = appState.isLoggedIn && submittableProfiles.isNotEmpty && session.profile.isSubmittable;
|
final allowSubmit = appState.isLoggedIn &&
|
||||||
|
submittableProfiles.isNotEmpty &&
|
||||||
|
session.profile != null &&
|
||||||
|
session.profile!.isSubmittable;
|
||||||
|
|
||||||
void _openRefineTags() async {
|
void _openRefineTags() async {
|
||||||
final result = await Navigator.push<OperatorProfile?>(
|
final result = await Navigator.push<OperatorProfile?>(
|
||||||
@@ -73,13 +76,13 @@ class EditNodeSheet extends StatelessWidget {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(locService.t('editNode.profile')),
|
title: Text(locService.t('editNode.profile')),
|
||||||
trailing: DropdownButton<NodeProfile>(
|
trailing: DropdownButton<NodeProfile?>(
|
||||||
value: session.profile,
|
value: session.profile,
|
||||||
|
hint: Text(locService.t('editNode.selectProfile')),
|
||||||
items: submittableProfiles
|
items: submittableProfiles
|
||||||
.map((p) => DropdownMenuItem(value: p, child: Text(p.name)))
|
.map((p) => DropdownMenuItem(value: p, child: Text(p.name)))
|
||||||
.toList(),
|
.toList(),
|
||||||
onChanged: (p) =>
|
onChanged: (p) => appState.updateEditSession(profile: p),
|
||||||
appState.updateEditSession(profile: p ?? session.profile),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -90,12 +93,12 @@ class EditNodeSheet extends StatelessWidget {
|
|||||||
divisions: 359,
|
divisions: 359,
|
||||||
value: session.directionDegrees,
|
value: session.directionDegrees,
|
||||||
label: session.directionDegrees.round().toString(),
|
label: session.directionDegrees.round().toString(),
|
||||||
onChanged: session.profile.requiresDirection
|
onChanged: (session.profile != null && session.profile!.requiresDirection)
|
||||||
? (v) => appState.updateEditSession(directionDeg: v)
|
? (v) => appState.updateEditSession(directionDeg: v)
|
||||||
: null, // Disables slider when requiresDirection is false
|
: null, // Disabled when no profile selected or profile doesn't require direction
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!session.profile.requiresDirection)
|
if (session.profile != null && !session.profile!.requiresDirection)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -143,7 +146,23 @@ class EditNodeSheet extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else if (!session.profile.isSubmittable)
|
else if (session.profile == null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.info_outline, color: Colors.orange, size: 20),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
locService.t('editNode.profileRequired'),
|
||||||
|
style: const TextStyle(color: Colors.orange, fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else if (!session.profile!.isSubmittable)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -165,7 +184,7 @@ class EditNodeSheet extends StatelessWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
onPressed: _openRefineTags,
|
onPressed: session.profile != null ? _openRefineTags : null, // Disabled when no profile selected
|
||||||
icon: const Icon(Icons.tune),
|
icon: const Icon(Icons.tune),
|
||||||
label: Text(session.operatorProfile != null
|
label: Text(session.operatorProfile != null
|
||||||
? locService.t('editNode.refineTagsWithProfile', params: [session.operatorProfile!.name])
|
? locService.t('editNode.refineTagsWithProfile', params: [session.operatorProfile!.name])
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class DirectionConesBuilder {
|
|||||||
final overlays = <Polygon>[];
|
final overlays = <Polygon>[];
|
||||||
|
|
||||||
// Add session cone if in add-camera mode and profile requires direction
|
// Add session cone if in add-camera mode and profile requires direction
|
||||||
if (session != null && session.target != null && session.profile.requiresDirection) {
|
if (session != null && session.target != null && session.profile?.requiresDirection == true) {
|
||||||
overlays.add(_buildCone(
|
overlays.add(_buildCone(
|
||||||
session.target!,
|
session.target!,
|
||||||
session.directionDegrees,
|
session.directionDegrees,
|
||||||
@@ -30,7 +30,7 @@ class DirectionConesBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add edit session cone if in edit-camera mode and profile requires direction
|
// Add edit session cone if in edit-camera mode and profile requires direction
|
||||||
if (editSession != null && editSession.profile.requiresDirection) {
|
if (editSession != null && editSession.profile?.requiresDirection == true) {
|
||||||
overlays.add(_buildCone(
|
overlays.add(_buildCone(
|
||||||
editSession.target,
|
editSession.target,
|
||||||
editSession.directionDegrees,
|
editSession.directionDegrees,
|
||||||
|
|||||||
Reference in new issue
Block a user