Skip to content
This repository has been archived by the owner on Jan 6, 2025. It is now read-only.

Commit

Permalink
Merge pull request #96 from nobelization/75-create-a-screen-to-displa…
Browse files Browse the repository at this point in the history
…y-the-status-of-our-sequences

75 create a screen to display the status of our sequences
  • Loading branch information
OtterWays authored Aug 23, 2024
2 parents dc038ed + 7868d8c commit a92e9e4
Show file tree
Hide file tree
Showing 16 changed files with 886 additions and 281 deletions.
10 changes: 5 additions & 5 deletions lib/component/app_bar.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
part of panoramax;

PreferredSizeWidget PanoramaxAppBar({context, title = "Panoramax"}) {
PreferredSizeWidget PanoramaxAppBar(
{context, title = "Panoramax", backEnabled = true}) {
return AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(
title
),
title: Text(title),
automaticallyImplyLeading: backEnabled,
);
}
}
330 changes: 330 additions & 0 deletions lib/component/sequence_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
part of panoramax;

class SequenceCard extends StatefulWidget {
const SequenceCard(this.sequence, {this.sequenceCount, super.key});

final GeoVisioLink sequence;
final int?
sequenceCount; //if sequenceCount is not null, there are photos being uploaded

@override
State<StatefulWidget> createState() => _SequenceCardState();
}

class _SequenceCardState extends State<SequenceCard> {
late int itemCount;
GeoVisioCollectionImportStatus? geovisioStatus;
Timer? timer;
SequenceState sequenceState = SequenceState.SENDING;
MemoryImage? image;

@override
void initState() {
super.initState();
itemCount = widget.sequence.stats_items!.count;
checkSequenceState();
getImage();
if ((sequenceState != SequenceState.READY &&
sequenceState != SequenceState.HIDDEN) ||
widget.sequenceCount != null) {
timer = Timer.periodic(Duration(seconds: 5), (timer) {
getStatus();
});
}
}

void getImage() async {
MemoryImage? imageRefresh;
try {
imageRefresh = await CollectionsApi.INSTANCE
.getThumbernail(collectionId: widget.sequence.id!);
} catch (e) {
print(e);
} finally {
setState(() {
image = imageRefresh;
});
}
}

void checkSequenceState() {
int count = geovisioStatus?.items
.where(
(element) => element.status == "ready",
)
.length ??
0;
print("checkSequenceStat");
setState(() {
sequenceState = geovisioStatus?.status == "deleted"
? SequenceState.DELETED
: widget.sequence.geovisio_status == "hidden"
? SequenceState.HIDDEN
: widget.sequenceCount == null
? widget.sequence.geovisio_status == "ready"
? SequenceState.READY
: SequenceState.BLURRING
: widget.sequenceCount != geovisioStatus?.items.length
? SequenceState.SENDING
: count == widget.sequenceCount
? SequenceState.READY
: SequenceState.BLURRING;
});
if (sequenceState == SequenceState.DELETED) {
timer?.cancel();
}
}

@override
void dispose() {
timer?.cancel();
super.dispose();
}

Future<void> getStatus() async {
GeoVisioCollectionImportStatus? geovisioStatusRefresh;
try {
geovisioStatusRefresh = await CollectionsApi.INSTANCE
.getGeovisioStatus(collectionId: widget.sequence.id!);
} catch (e) {
print(e);
} finally {
setState(() {
geovisioStatus = geovisioStatusRefresh;
checkSequenceState();
});
}
}

Future<void> openUrl() async {
final instance = await getInstance();
final Uri url =
Uri.https("panoramax.$instance.fr", '/sequence/${widget.sequence.id}');
if (!await launchUrl(url)) {
throw Exception("Could not launch $url");
}
}

Future<void> shareUrl() async {
final instance = await getInstance();
final url = "panoramax.$instance.fr/sequence/${widget.sequence.id}";
await Share.share(url);
}

@override
Widget build(BuildContext context) {
return sequenceState == SequenceState.DELETED
? Container()
: GestureDetector(
onTap: openUrl,
child: Container(
margin: const EdgeInsets.all(10),
width: double.infinity,
decoration: BoxDecoration(
color: sequenceState == SequenceState.HIDDEN
? Colors.grey.shade400
: Colors.white,
borderRadius: const BorderRadius.all(
Radius.circular(18),
),
boxShadow: [
BoxShadow(
color: Colors.grey.shade200,
spreadRadius: 4,
blurRadius: 6,
offset: const Offset(0, 3),
),
],
),
child: Column(children: [
sequenceState == SequenceState.READY ||
sequenceState == SequenceState.HIDDEN
? Picture()
: Loader(),
PictureDetail(),
]),
));
}

Widget PictureDetail() {
return Container(
margin: const EdgeInsets.fromLTRB(10, 10, 10, 0),
child: Column(
children: [
PictureCount(),
Shooting(),
sequenceState == SequenceState.READY ||
sequenceState == SequenceState.HIDDEN
? Publishing()
: Container(),
sequenceState == SequenceState.BLURRING ? Blurring() : Container()
],
));
}

Widget PictureCount() {
final count =
widget.sequenceCount == null ? itemCount : widget.sequenceCount;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [
Text(
'$count ${AppLocalizations.of(context)!.pictures}',
style: GoogleFonts.nunito(
fontSize: 18,
fontWeight: FontWeight.w800,
),
),
]),
sequenceState == SequenceState.READY ||
sequenceState == SequenceState.HIDDEN
? FloatingActionButton(
onPressed: shareUrl,
child: Icon(
Icons.share,
//size: 14,
),
shape: CircleBorder(),
mini: true,
backgroundColor: Colors.grey,
tooltip: AppLocalizations.of(context)!.share)
: Container(),
],
);
}

Widget Shooting() {
String? date = widget.sequence.extent?.temporal?.interval?[0]?[0];
DateFormat dateFormat = DateFormat.yMMMd('fr_FR').add_Hm();
return Row(
children: [
const Icon(Icons.photo_camera),
Padding(
padding: EdgeInsets.all(8),
child: Text(AppLocalizations.of(context)!.shooting)),
Spacer(),
Text(date == null ? "" : dateFormat.format(DateTime.parse(date)))
],
);
}

Widget Publishing() {
DateFormat dateFormat = DateFormat.yMMMd('fr_FR').add_Hm();
String? date = widget.sequence.created;
return Row(
children: [
const Icon(Icons.cloud_upload),
Padding(
padding: EdgeInsets.all(8),
child: Text(AppLocalizations.of(context)!.publishing)),
Spacer(),
Text(date == null ? "" : dateFormat.format(DateTime.parse(date)))
],
);
}

Widget Loader() {
return Container(
height: 140,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(18),
topRight: Radius.circular(18),
),
),
child: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
sequenceState == SequenceState.BLURRING
? Icon(
Icons.check_circle_outline,
color: Colors.blue,
size: 60,
)
: CircularProgressIndicator(
strokeWidth: 4, // thickness of the circle
color: Colors.blue, // color of the progress bar
),
Text(sequenceState == SequenceState.BLURRING
? AppLocalizations.of(context)!.sendingCompleted
: AppLocalizations.of(context)!.sendingInProgress)
]))));
}

Widget Picture() {
return ClipRect(
child: Stack(
children: [
if (image != null && image is MemoryImage)
Container(
height: 180,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(18),
topRight: Radius.circular(18),
),
image: DecorationImage(
image: image!,
fit: BoxFit.cover,
))),
if (sequenceState == SequenceState.HIDDEN)
ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.transparent,
height: 180,
width: double.infinity, // or a specific width
),
),
),
if (sequenceState == SequenceState.HIDDEN)
Container(
height: 180,
child: Center(
child: Text(
AppLocalizations.of(context)!.hidden,
style: GoogleFonts.nunito(
fontSize: 18,
fontWeight: FontWeight.w800,
color: Colors.white),
)))
],
),
);
}

Widget Blurring() {
int count = geovisioStatus?.items
.where(
(element) => element.status == "ready",
)
.length ??
0;
double total = geovisioStatus?.items.length.toDouble() ?? 0;
return Container(
child: Column(
children: [
LinearProgressIndicator(
value: (total == 0) ? 0 : count / total, //don't divide by 0 !
semanticsLabel: AppLocalizations.of(context)!.blurringInProgress,
minHeight: 16,
borderRadius: BorderRadius.circular(8),
),
Row(
children: [
const Icon(Icons.blur_on_outlined),
Padding(
padding: EdgeInsets.all(8),
child: Text(AppLocalizations.of(context)!.blurringInProgress))
],
)
],
));
}
}

enum SequenceState { SENDING, BLURRING, READY, DELETED, HIDDEN }
1 change: 0 additions & 1 deletion lib/constant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ import 'package:flutter/material.dart';
const MaterialColor DEFAULT_COLOR = Colors.indigo;
const bool API_IS_HTTPS = false;
const Color BLUE = Color(0xFF010D37);
String API_HOSTNAME = 'openstreetmap';
10 changes: 10 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
"emptyError": "No element found",
"loading": "Loading...",

"mySequences": "My sequence",
"pictures": "picture(s)",
"shooting": "Shooting",
"sendingInProgress": "Sending in progress",
"sendingCompleted": "Sending completed",
"publishing": "Publishing",
"blurringInProgress": "Blurring in progress",
"share": "Share",
"hidden": "Hidden sequence",

"capture": "Take a picture",
"createSequenceWithPicture_tooltip": "Create a new sequence with captured pictures",
"noCameraFoundError": "No camera found for this device",
Expand Down
10 changes: 10 additions & 0 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
"emptyError": "Aucun élément trouvé",
"loading": "Chargement...",

"mySequences": "Mes séquences",
"pictures": "photo(s)",
"shooting": "Prise de vue",
"sendingInProgress": "Envoi en cours",
"sendingCompleted": "Envoi terminé",
"publishing": "Publication",
"blurringInProgress": "Floutage en cours",
"share": "Partager",
"hidden": "Séquence masquée",

"capture": "Prendre une photo",
"createSequenceWithPicture_tooltip": "Créer une nouvelle séquence avec les photos prises",
"noCameraFoundError": "Pas de caméra trouvée pour cet appareil",
Expand Down
Loading

0 comments on commit a92e9e4

Please sign in to comment.