mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Compare commits
1 Commits
v2026.0306
...
v2026.0306
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70a6156e8a |
@@ -489,7 +489,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 92;
|
CURRENT_PROJECT_VERSION = 94;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -511,7 +511,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 92;
|
CURRENT_PROJECT_VERSION = 94;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -530,7 +530,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 92;
|
CURRENT_PROJECT_VERSION = 94;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 92;
|
CURRENT_PROJECT_VERSION = 94;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -679,7 +679,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 92;
|
CURRENT_PROJECT_VERSION = 94;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -702,7 +702,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 92;
|
CURRENT_PROJECT_VERSION = 94;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>92</string>
|
<string>94</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||||
|
|||||||
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000216">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000555">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.451844">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.42343">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="110.228647">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="91.987634">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="475.510001">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="184.536223">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -466,7 +466,10 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add to messages list with "sending" status
|
// Add to messages list with "sending" status
|
||||||
messagesProvider.addSentMessage(sentMessage);
|
messagesProvider.addSentMessage(
|
||||||
|
sentMessage,
|
||||||
|
contact: _selectedRecipient,
|
||||||
|
);
|
||||||
|
|
||||||
// Send message to selected recipient
|
// Send message to selected recipient
|
||||||
final sentSuccessfully = await connectionProvider.sendTextMessage(
|
final sentSuccessfully = await connectionProvider.sendTextMessage(
|
||||||
@@ -1498,145 +1501,163 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
return Consumer<MessagesProvider>(
|
return Consumer<MessagesProvider>(
|
||||||
builder: (context, messagesProvider, child) {
|
builder: (context, messagesProvider, child) {
|
||||||
final messages = _getFilteredMessages(messagesProvider);
|
final messages = _getFilteredMessages(messagesProvider);
|
||||||
|
final bottomInset = MediaQuery.of(context).viewPadding.bottom;
|
||||||
|
final composerBottomPadding = bottomInset > 0 ? 2.0 : 10.0;
|
||||||
|
|
||||||
return Column(
|
return GestureDetector(
|
||||||
children: [
|
behavior: HitTestBehavior.translucent,
|
||||||
// Messages list with pull-to-refresh
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
Expanded(
|
child: Column(
|
||||||
child: RefreshIndicator(
|
children: [
|
||||||
onRefresh: _handleRefresh,
|
// Messages list with pull-to-refresh
|
||||||
child: messages.isEmpty
|
Expanded(
|
||||||
? LayoutBuilder(
|
child: RefreshIndicator(
|
||||||
builder: (context, constraints) =>
|
onRefresh: _handleRefresh,
|
||||||
SingleChildScrollView(
|
child: messages.isEmpty
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
? LayoutBuilder(
|
||||||
child: ConstrainedBox(
|
builder: (context, constraints) =>
|
||||||
constraints: BoxConstraints(
|
SingleChildScrollView(
|
||||||
minHeight: constraints.maxHeight,
|
keyboardDismissBehavior:
|
||||||
),
|
ScrollViewKeyboardDismissBehavior.onDrag,
|
||||||
child: Center(
|
physics:
|
||||||
child: Column(
|
const AlwaysScrollableScrollPhysics(),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: ConstrainedBox(
|
||||||
children: [
|
constraints: BoxConstraints(
|
||||||
Icon(
|
minHeight: constraints.maxHeight,
|
||||||
Icons.message_outlined,
|
),
|
||||||
size: 64,
|
child: Center(
|
||||||
color: Theme.of(context).disabledColor,
|
child: Column(
|
||||||
),
|
mainAxisAlignment:
|
||||||
const SizedBox(height: 16),
|
MainAxisAlignment.center,
|
||||||
Text(
|
children: [
|
||||||
AppLocalizations.of(
|
Icon(
|
||||||
context,
|
Icons.message_outlined,
|
||||||
)!.noMessagesYet,
|
size: 64,
|
||||||
style: Theme.of(
|
color: Theme.of(
|
||||||
context,
|
context,
|
||||||
).textTheme.titleLarge,
|
).disabledColor,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
AppLocalizations.of(
|
AppLocalizations.of(
|
||||||
context,
|
context,
|
||||||
)!.pullDownToSync,
|
)!.noMessagesYet,
|
||||||
style: Theme.of(
|
style: Theme.of(
|
||||||
context,
|
context,
|
||||||
).textTheme.bodyMedium,
|
).textTheme.titleLarge,
|
||||||
textAlign: TextAlign.center,
|
),
|
||||||
),
|
const SizedBox(height: 8),
|
||||||
],
|
Text(
|
||||||
|
AppLocalizations.of(
|
||||||
|
context,
|
||||||
|
)!.pullDownToSync,
|
||||||
|
style: Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.bodyMedium,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
)
|
: ListView.builder(
|
||||||
: ListView.builder(
|
controller: _scrollController,
|
||||||
controller: _scrollController,
|
keyboardDismissBehavior:
|
||||||
reverse: true,
|
ScrollViewKeyboardDismissBehavior.onDrag,
|
||||||
padding: const EdgeInsets.all(8),
|
reverse: true,
|
||||||
itemCount: messages.length,
|
padding: const EdgeInsets.all(8),
|
||||||
itemBuilder: (context, index) {
|
itemCount: messages.length,
|
||||||
final message = messages[index];
|
itemBuilder: (context, index) {
|
||||||
final isHighlighted =
|
final message = messages[index];
|
||||||
message.id == _highlightedMessageId;
|
final isHighlighted =
|
||||||
|
message.id == _highlightedMessageId;
|
||||||
|
|
||||||
return MessageBubble(
|
return MessageBubble(
|
||||||
key: ValueKey(message.id),
|
key: ValueKey(message.id),
|
||||||
message: message,
|
message: message,
|
||||||
isHighlighted: isHighlighted,
|
isHighlighted: isHighlighted,
|
||||||
onNavigateToMap: widget.onNavigateToMap,
|
onNavigateToMap: widget.onNavigateToMap,
|
||||||
onTap:
|
onTap:
|
||||||
widget.onNavigateToMap != null &&
|
widget.onNavigateToMap != null &&
|
||||||
message.isSarMarker &&
|
message.isSarMarker &&
|
||||||
message.sarGpsCoordinates != null
|
message.sarGpsCoordinates != null
|
||||||
? () {
|
? () {
|
||||||
final mapProvider = context
|
final mapProvider = context
|
||||||
.read<MapProvider>();
|
.read<MapProvider>();
|
||||||
mapProvider.navigateToLocation(
|
mapProvider.navigateToLocation(
|
||||||
location: message.sarGpsCoordinates!,
|
location: message.sarGpsCoordinates!,
|
||||||
zoom: 15.0,
|
zoom: 15.0,
|
||||||
);
|
);
|
||||||
widget.onNavigateToMap?.call();
|
widget.onNavigateToMap?.call();
|
||||||
}
|
}
|
||||||
: widget.onNavigateToMap != null &&
|
: widget.onNavigateToMap != null &&
|
||||||
message.isDrawing &&
|
message.isDrawing &&
|
||||||
message.drawingId != null
|
message.drawingId != null
|
||||||
? () {
|
? () {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
'🗺️ [MessagesTab] Drawing tapped! ID: ${message.drawingId}',
|
'🗺️ [MessagesTab] Drawing tapped! ID: ${message.drawingId}',
|
||||||
);
|
);
|
||||||
final mapProvider = context
|
final mapProvider = context
|
||||||
.read<MapProvider>();
|
.read<MapProvider>();
|
||||||
final drawingProvider = context
|
final drawingProvider = context
|
||||||
.read<DrawingProvider>();
|
.read<DrawingProvider>();
|
||||||
mapProvider.navigateToDrawing(
|
mapProvider.navigateToDrawing(
|
||||||
message.drawingId!,
|
message.drawingId!,
|
||||||
drawingProvider,
|
drawingProvider,
|
||||||
);
|
);
|
||||||
widget.onNavigateToMap?.call();
|
widget.onNavigateToMap?.call();
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
// Message input area
|
// Message input area
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SafeArea(
|
SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
|
padding: EdgeInsets.fromLTRB(
|
||||||
child: Container(
|
10,
|
||||||
decoration: BoxDecoration(
|
10,
|
||||||
color: Theme.of(
|
10,
|
||||||
context,
|
composerBottomPadding,
|
||||||
).colorScheme.surfaceContainerLow,
|
),
|
||||||
borderRadius: BorderRadius.circular(28),
|
child: Container(
|
||||||
border: Border.all(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(
|
color: Theme.of(
|
||||||
context,
|
context,
|
||||||
).dividerColor.withValues(alpha: 0.35),
|
).colorScheme.surfaceContainerLow,
|
||||||
),
|
borderRadius: BorderRadius.circular(28),
|
||||||
boxShadow: [
|
border: Border.all(
|
||||||
BoxShadow(
|
color: Theme.of(
|
||||||
color: Colors.black.withValues(alpha: 0.05),
|
context,
|
||||||
blurRadius: 18,
|
).dividerColor.withValues(alpha: 0.35),
|
||||||
offset: const Offset(0, 6),
|
|
||||||
),
|
),
|
||||||
],
|
boxShadow: [
|
||||||
),
|
BoxShadow(
|
||||||
child: Padding(
|
color: Colors.black.withValues(alpha: 0.05),
|
||||||
padding: const EdgeInsets.fromLTRB(10, 10, 10, 8),
|
blurRadius: 18,
|
||||||
child: Column(
|
offset: const Offset(0, 6),
|
||||||
mainAxisSize: MainAxisSize.min,
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
],
|
||||||
children: [
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 10, 10, 8),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
@@ -1860,20 +1881,52 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
excludeFromSemantics: true,
|
excludeFromSemantics: true,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
excludeFromSemantics: true,
|
excludeFromSemantics: true,
|
||||||
|
onTap: canSendText
|
||||||
|
? () {
|
||||||
|
debugPrint(
|
||||||
|
'👆 [MessagesTab] Send button tapped '
|
||||||
|
'(canSendText=$canSendText, '
|
||||||
|
'textLength=${_textController.text.trim().length}, '
|
||||||
|
'recording=$_isRecording, '
|
||||||
|
'sendingVoice=$_isSendingVoice)',
|
||||||
|
);
|
||||||
|
_sendMessage();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
onLongPressStart:
|
onLongPressStart:
|
||||||
(_voiceSupported &&
|
(_voiceSupported &&
|
||||||
!_isSendingVoice)
|
!_isSendingVoice)
|
||||||
? (_) => _startVoiceRecording()
|
? (_) {
|
||||||
|
debugPrint(
|
||||||
|
'🎙️ [MessagesTab] Send button long-press start '
|
||||||
|
'(voiceSupported=$_voiceSupported, '
|
||||||
|
'sendingVoice=$_isSendingVoice, '
|
||||||
|
'recording=$_isRecording)',
|
||||||
|
);
|
||||||
|
_startVoiceRecording();
|
||||||
|
}
|
||||||
: null,
|
: null,
|
||||||
onLongPressEnd:
|
onLongPressEnd:
|
||||||
(_voiceSupported &&
|
(_voiceSupported &&
|
||||||
_isRecording)
|
_isRecording)
|
||||||
? (_) => _stopAndSendVoice()
|
? (_) {
|
||||||
|
debugPrint(
|
||||||
|
'🎙️ [MessagesTab] Send button long-press end '
|
||||||
|
'(recording=$_isRecording)',
|
||||||
|
);
|
||||||
|
_stopAndSendVoice();
|
||||||
|
}
|
||||||
: null,
|
: null,
|
||||||
onLongPressCancel:
|
onLongPressCancel:
|
||||||
(_voiceSupported &&
|
(_voiceSupported &&
|
||||||
_isRecording)
|
_isRecording)
|
||||||
? () => _stopAndSendVoice()
|
? () {
|
||||||
|
debugPrint(
|
||||||
|
'🎙️ [MessagesTab] Send button long-press cancel '
|
||||||
|
'(recording=$_isRecording)',
|
||||||
|
);
|
||||||
|
_stopAndSendVoice();
|
||||||
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -1993,16 +2046,17 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2026.0306.2+12
|
version: 2026.0306.3+13
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.9.2
|
sdk: ^3.9.2
|
||||||
|
|||||||
Reference in New Issue
Block a user