Compare commits

...

1 Commits

Author SHA1 Message Date
Janez T
70a6156e8a Update iOS project version 2026-03-06 21:22:51 +01:00
5 changed files with 204 additions and 150 deletions

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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> {
), ),
], ],
), ),
], ],
),
), ),
), ),
), ),
), ),
), ],
], ),
), ),
), ],
], ),
); );
}, },
); );

View File

@@ -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