Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve application #18

Merged
merged 6 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/deploy-hosting-pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ jobs:
- shell: bash
env:
FIREBASE_APP_CONFIGURE_DEV: ${{ secrets.FIREBASE_APP_CONFIGURE_DEV }}
# ビルドを通すためにとりあえずファイルを作る。デプロイはしない
run: |
echo "$FIREBASE_APP_CONFIGURE_DEV" > lib/firebase_options/dev.dart
echo "$FIREBASE_APP_CONFIGURE_DEV" > lib/firebase_options/prod.dart
touch key.env
- uses: kuhnroyal/flutter-fvm-config-action@v2
id: fvm-config-action
Expand Down
6 changes: 6 additions & 0 deletions app/radio_qth_map/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
"channel": "Channel",
"channel_error": "Either channel or mode is required.",
"citizens_band": "CB",
"close": "Close",
"confim": "Confirm",
"contact_us": "Contact us",
"copied_to_clipboard": "Copied to clipboard",
"copy_to_clipboard": "Copy to clipboard",
"dcr": "DCR",
"delete": "Delete",
"delete_operation_confirm_message": "Are you sure you want to delete?",
Expand Down Expand Up @@ -43,6 +46,9 @@
"publish_log": "Publish log",
"publish_log_tooltip": "To publish logs, please add logs",
"search": "Search(Not yet implemented)",
"share": "Share",
"share_operation_format": "To check the log operated by {callsign} on {date} on the map.",
"share_with_x": "To post on X (Twitter)",
"start": "Start",
"terms_of_use": "Terms of use",
"time_error": "Either Start or End is required",
Expand Down
6 changes: 6 additions & 0 deletions app/radio_qth_map/lib/l10n/app_ja.arb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
"channel": "チャンネル",
"channel_error": "チャンネルか種別は必須です",
"citizens_band": "CB",
"close": "閉じる",
"confim": "確認",
"contact_us": "お問い合わせ",
"copied_to_clipboard": "クリップボードにコピーしました",
"copy_to_clipboard": "クリップボードにコピーする",
"dcr": "DCR",
"delete": "削除",
"delete_operation_confirm_message": "このデータを削除して良いですか",
Expand Down Expand Up @@ -43,6 +46,9 @@
"publish_log": "ログを公開する",
"publish_log_tooltip": "ログを公開するには、ログを追加してください",
"search": "検索(現在未実装です)",
"share": "共有する",
"share_operation_format": "{callsign} が {date} に運用したログを地図で確認する",
"share_with_x": "X(Twitter)に投稿する",
"start": "開始",
"terms_of_use": "利用規約",
"time_error": "開始または終了時間は必須です",
Expand Down
17 changes: 14 additions & 3 deletions app/radio_qth_map/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:radio_qth_map/main_router.dart';
import 'package:radio_qth_map/repository/firestore_repository.dart';
import 'package:radio_qth_map/repository/locale_notifier.dart';
import 'package:responsive_framework/responsive_framework.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:radio_qth_map/firebase_options/dev.dart' as dev;
import 'package:radio_qth_map/firebase_options/prod.dart' as prod;

void main() async {
usePathUrlStrategy();
await dotenv.load(fileName: 'key.env');
await Firebase.initializeApp(
options: dev.firebaseOptions,
);
if (dotenv.maybeGet('ENVIRONMENT') == 'prod') {
await Firebase.initializeApp(
options: prod.firebaseOptions,
);
} else {
await Firebase.initializeApp(
options: dev.firebaseOptions,
);
}
final firestore = FirebaseFirestore.instance;
if (dotenv.maybeGet('USE_FIRESTORE_EMULATOR') == 'true') {
firestore.useFirestoreEmulator('localhost', 8080);
Expand Down Expand Up @@ -50,6 +58,9 @@ class MyApp extends StatelessWidget {
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xff24c5be)),
useMaterial3: true,
textTheme: GoogleFonts.notoSansTextTheme(
Theme.of(context).textTheme,
),
),
routerConfig: router,
builder: (context, child) {
Expand Down
5 changes: 4 additions & 1 deletion app/radio_qth_map/lib/repository/firestore_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ class FirestoreRepository {
return operation;
}

Future<void> storeOperations(List<OperationRowData> operations) async {
/// 運用情報を保存する
/// operationIdを返す
Future<String> storeOperations(List<OperationRowData> operations) async {
// 運用開始・終了時間のリストを作る
final operationTimes = operations
.map((e) => [e.startTime, e.endTime])
Expand Down Expand Up @@ -166,6 +168,7 @@ class FirestoreRepository {
}
}
await batch.commit();
return newOperationDoc.id;
}

Stream<List<QsoWithOperation>> qsoWithOperation({
Expand Down
205 changes: 110 additions & 95 deletions app/radio_qth_map/lib/screen/add_operation_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ class _AddOperationScreenState extends State<AddOperationScreen> {
? null
: () async {
final repository = context.read<FirestoreRepository>();
await repository.storeOperations(_logList);
final id = await repository.storeOperations(_logList);
if (context.mounted) {
context.pop();
context.pop(id);
}
},
label: Text(AppLocalizations.of(context)!.publish_log),
Expand All @@ -68,111 +68,126 @@ class _AddOperationScreenState extends State<AddOperationScreen> {
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(AppLocalizations.of(context)!.my_statio_settings),
ValueListenableBuilder(
valueListenable: _licenseModeNotifier,
builder: (context, type, _) {
return _MyOperationInfoInputForm(
key: _myOperationInfoKey,
// 1運用につき1ライセンスタイプとするので、運用情報がある場合はコールサインを変更できないようにする
canChangeCallsign: _logList.isEmpty,
licenseType: type,
);
}),
const SizedBox(
height: 8,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Text(AppLocalizations.of(context)!.my_statio_settings),
),
SliverToBoxAdapter(
child: ValueListenableBuilder(
valueListenable: _licenseModeNotifier,
builder: (context, type, _) {
return _MyOperationInfoInputForm(
key: _myOperationInfoKey,
// 1運用につき1ライセンスタイプとするので、運用情報がある場合はコールサインを変更できないようにする
canChangeCallsign: _logList.isEmpty,
licenseType: type,
);
}),
),
const SliverToBoxAdapter(
child: SizedBox(
height: 8,
),
),
SliverToBoxAdapter(
child: Text(AppLocalizations.of(context)!.other_station_settings),
),
Text(AppLocalizations.of(context)!.other_station_settings),
ValueListenableBuilder(
SliverToBoxAdapter(
child: ValueListenableBuilder(
valueListenable: _licenseModeNotifier,
builder: (context, type, _) {
return _OtherStationInfoInputForm(
key: _otherStationInfoKey,
licenseType: type,
);
}),
const SizedBox(
height: 8,
),
ElevatedButton.icon(
onPressed: () {
if (_myOperationInfoKey.currentState?.validate() == true &&
_otherStationInfoKey.currentState?.validate() == true) {
final myOperationInfo = _myOperationInfoKey.currentState!;
final otherStationInfo = _otherStationInfoKey.currentState!;
final operationRowData = OperationRowData(
myCallsign: myOperationInfo.callsignController.text,
myGridlocator: myOperationInfo.gridlocatorController.text,
myLatitude: double.tryParse(
myOperationInfo.latitudeController.text,
),
myLongitude: double.tryParse(
myOperationInfo.longitudeController.text,
),
frequency: double.tryParse(
myOperationInfo.frequencyController.text,
),
band: myOperationInfo.band,
amateurRadioMode: myOperationInfo.amateurRadioMode,
freeLicenseMode: myOperationInfo.freeLicenseMode,
channel: int.tryParse(
myOperationInfo.channelController.text,
),
power: double.tryParse(
myOperationInfo.powerController.text,
),
otherCallsign: otherStationInfo.callsignController.text,
otherGridlocator:
otherStationInfo.gridlocatorController.text,
otherLatitude: double.tryParse(
otherStationInfo.latitudeController.text,
),
otherLongitude: double.tryParse(
otherStationInfo.longitudeController.text,
),
startTime: DateTimeExtension.tryParseUTC(
otherStationInfo.startController.text,
),
endTime: DateTimeExtension.tryParseUTC(
otherStationInfo.endController.text,
),
srst: int.tryParse(
otherStationInfo.srstController.text,
),
rrst: int.tryParse(
otherStationInfo.rrstController.text,
),
);
setState(() {
_logList.add(operationRowData);
});
otherStationInfo.reset();
}
},
icon: const Icon(Icons.add),
label: Text(
AppLocalizations.of(context)!.add_qso,
},
),
),
const SizedBox(
height: 8,
const SliverToBoxAdapter(
child: SizedBox(
height: 8,
),
),
Expanded(
child: ListView.builder(
itemCount: _logList.length,
itemBuilder: (context, index) {
return OperationRow(
data: _logList[index],
onTapDelete: () {
setState(() {
_logList.removeAt(index);
});
},
);
SliverToBoxAdapter(
child: ElevatedButton.icon(
onPressed: () {
if (_myOperationInfoKey.currentState?.validate() == true &&
_otherStationInfoKey.currentState?.validate() == true) {
final myOperationInfo = _myOperationInfoKey.currentState!;
final otherStationInfo = _otherStationInfoKey.currentState!;
final operationRowData = OperationRowData(
myCallsign: myOperationInfo.callsignController.text,
myGridlocator: myOperationInfo.gridlocatorController.text,
myLatitude: double.tryParse(
myOperationInfo.latitudeController.text,
),
myLongitude: double.tryParse(
myOperationInfo.longitudeController.text,
),
frequency: double.tryParse(
myOperationInfo.frequencyController.text,
),
band: myOperationInfo.band,
amateurRadioMode: myOperationInfo.amateurRadioMode,
freeLicenseMode: myOperationInfo.freeLicenseMode,
channel: int.tryParse(
myOperationInfo.channelController.text,
),
power: double.tryParse(
myOperationInfo.powerController.text,
),
otherCallsign: otherStationInfo.callsignController.text,
otherGridlocator:
otherStationInfo.gridlocatorController.text,
otherLatitude: double.tryParse(
otherStationInfo.latitudeController.text,
),
otherLongitude: double.tryParse(
otherStationInfo.longitudeController.text,
),
startTime: DateTimeExtension.tryParseUTC(
otherStationInfo.startController.text,
),
endTime: DateTimeExtension.tryParseUTC(
otherStationInfo.endController.text,
),
srst: int.tryParse(
otherStationInfo.srstController.text,
),
rrst: int.tryParse(
otherStationInfo.rrstController.text,
),
);
setState(() {
_logList.add(operationRowData);
});
otherStationInfo.reset();
}
},
icon: const Icon(Icons.add),
label: Text(
AppLocalizations.of(context)!.add_qso,
),
),
),
const SliverToBoxAdapter(
child: SizedBox(
height: 8,
),
),
SliverList.builder(
itemCount: _logList.length,
itemBuilder: (context, index) {
return OperationRow(
data: _logList[index],
onTapDelete: () {
setState(() {
_logList.removeAt(index);
});
},
);
},
)
],
),
Expand Down
20 changes: 16 additions & 4 deletions app/radio_qth_map/lib/screen/introduce_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ class IntroduceScreen extends StatelessWidget {
slivers: [
SliverAppBar(
pinned: true,
expandedHeight: 800,
expandedHeight: 400,
title: const Text('QTH map'),
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background: SizedBox(
height: 800,
height: 400,
child: Stack(
children: [
Container(
Expand Down Expand Up @@ -409,8 +409,20 @@ class IntroduceScreen extends StatelessWidget {
),
),
const SliverToBoxAdapter(
child: SizedBox(height: 12),
)
child: SizedBox(height: 56),
),
SliverToBoxAdapter(
child: Container(
width: double.infinity,
alignment: Alignment.center,
child: TextButton(
onPressed: () {
launchUrl(Uri.parse('https://covelline.com'));
},
child: const Text('© covelline, LLC. 2023'),
),
),
),
],
),
);
Expand Down
Loading