mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-07-06 04:37:56 +02:00
Limit tag list size, make changelog use a list instead of \n, make links clickable in node tags
This commit is contained in:
@@ -17,6 +17,22 @@ class ChangelogService {
|
||||
Map<String, dynamic>? _changelogData;
|
||||
bool _initialized = false;
|
||||
|
||||
/// Parse changelog content from either string or array format
|
||||
String? _parseChangelogContent(dynamic content) {
|
||||
if (content == null) return null;
|
||||
|
||||
if (content is String) {
|
||||
// Legacy format: single string with \n
|
||||
return content.isEmpty ? null : content;
|
||||
} else if (content is List) {
|
||||
// New format: array of strings
|
||||
final lines = content.whereType<String>().where((line) => line.isNotEmpty).toList();
|
||||
return lines.isEmpty ? null : lines.join('\n');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Initialize the service by loading changelog data
|
||||
Future<void> init() async {
|
||||
if (_initialized) return;
|
||||
@@ -89,8 +105,7 @@ class ChangelogService {
|
||||
return null;
|
||||
}
|
||||
|
||||
final content = versionData['content'] as String?;
|
||||
return (content?.isEmpty == true) ? null : content;
|
||||
return _parseChangelogContent(versionData['content']);
|
||||
}
|
||||
|
||||
/// Get the changelog content that should be displayed (may be combined from multiple versions)
|
||||
@@ -112,8 +127,7 @@ class ChangelogService {
|
||||
final versionData = _changelogData![version] as Map<String, dynamic>?;
|
||||
if (versionData == null) return null;
|
||||
|
||||
final content = versionData['content'] as String?;
|
||||
return (content?.isEmpty == true) ? null : content;
|
||||
return _parseChangelogContent(versionData['content']);
|
||||
}
|
||||
|
||||
/// Get all changelog entries (for settings page)
|
||||
@@ -125,7 +139,7 @@ class ChangelogService {
|
||||
for (final entry in _changelogData!.entries) {
|
||||
final version = entry.key;
|
||||
final versionData = entry.value as Map<String, dynamic>?;
|
||||
final content = versionData?['content'] as String?;
|
||||
final content = _parseChangelogContent(versionData?['content']);
|
||||
|
||||
// Only include versions with non-empty content
|
||||
if (content != null && content.isNotEmpty) {
|
||||
@@ -203,7 +217,7 @@ class ChangelogService {
|
||||
for (final entry in _changelogData!.entries) {
|
||||
final version = entry.key;
|
||||
final versionData = entry.value as Map<String, dynamic>?;
|
||||
final content = versionData?['content'] as String?;
|
||||
final content = _parseChangelogContent(versionData?['content']);
|
||||
|
||||
// Skip versions with empty content
|
||||
if (content == null || content.isEmpty) continue;
|
||||
@@ -220,7 +234,7 @@ class ChangelogService {
|
||||
// Build changelog content
|
||||
final intermediateChangelogs = intermediateVersions.map((version) {
|
||||
final versionData = _changelogData![version] as Map<String, dynamic>;
|
||||
final content = versionData['content'] as String;
|
||||
final content = _parseChangelogContent(versionData['content'])!; // Safe to use ! here since we filtered empty content above
|
||||
return '**Version $version:**\n$content';
|
||||
}).toList();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||
import '../models/osm_node.dart';
|
||||
import '../app_state.dart';
|
||||
import '../services/localization_service.dart';
|
||||
@@ -127,12 +128,26 @@ class NodeTagSheet extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
e.value,
|
||||
child: Linkify(
|
||||
onOpen: (link) async {
|
||||
final uri = Uri.parse(link.url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} else if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Could not open URL: ${link.url}')),
|
||||
);
|
||||
}
|
||||
},
|
||||
text: e.value,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
|
||||
),
|
||||
softWrap: true,
|
||||
linkStyle: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -44,8 +44,16 @@ class SuspectedLocationSheet extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Display all fields
|
||||
...displayData.entries.map(
|
||||
// Constrain field list height to keep buttons visible
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.4, // Max 40% of screen height
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
// Display all fields
|
||||
...displayData.entries.map(
|
||||
(e) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
|
||||
Reference in New Issue
Block a user