Skip to content

Commit

Permalink
Merge pull request #42 from Metatavu/develop
Browse files Browse the repository at this point in the history
Production update 19.4.2024
  • Loading branch information
anttileppa committed Apr 19, 2024
2 parents 364d051 + 95cc9bd commit 16401ba
Show file tree
Hide file tree
Showing 19 changed files with 198 additions and 70 deletions.
4 changes: 4 additions & 0 deletions .fvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"flutter": "3.13.1",
"flavors": {}
}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,6 @@ metrics
android/key.properties

# Flutter version manager
.fvm/flutter_sdk

# FVM Version Cache
.fvm/
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"editor": {
"formatOnSave": true,
"formatOnType": true
}
},
"dart.flutterSdkPath": ".fvm/versions/3.13.1"
}
20 changes: 16 additions & 4 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:label="noheva_visitor_ui"
android:name="${applicationName}"
Expand All @@ -24,6 +30,16 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".NohevaVisitorUiBootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
Expand All @@ -40,8 +56,4 @@
android:resource="@xml/file_paths" />
</provider>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
</manifest>
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
package fi.metatavu.noheva_visitor_ui

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!Settings.canDrawOverlays(applicationContext)) {
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivityForResult(intent, REQUEST_OVERLAY_PERMISSIONS)

return
}
}

companion object {
const val REQUEST_OVERLAY_PERMISSIONS = 100
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fi.metatavu.noheva_visitor_ui;

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log

/**
* Broadcast receiver that starts main activity when device boots
*/
class NohevaVisitorUiBootReceiver: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(javaClass.name, "Received boot completed intent!")
val mainActivityIntent = Intent(context, MainActivity::class.java)
mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Log.d(javaClass.name, "Starting main activity...")
context.startActivity(mainActivityIntent)
}
}
25 changes: 15 additions & 10 deletions lib/screens/default_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class DefaultScreen extends StatefulWidget {
class _DefaultScreenState extends State<DefaultScreen> {
bool _isDeviceApproved = false;
late StreamSubscription<String?> _pageStreamSubscription;
Timer? _deviceApprovalTimer;

/// Navigates to [PageScreen] with [pageId]
void _navigateToPageScreen(String pageId) {
Expand All @@ -46,16 +47,19 @@ class _DefaultScreenState extends State<DefaultScreen> {
Future<void> _checkDeviceApproval() async {
final deviceIsApproved = await keyDao.checkIsDeviceApproved();
if (!deviceIsApproved) {
Timer.periodic(const Duration(seconds: 5), (timer) async {
SimpleLogger().info("Checking whether device has been approved...");
bool isApproved = await keyDao.checkIsDeviceApproved();
setState(() => _isDeviceApproved = isApproved);
if (isApproved) {
SimpleLogger().info("Device is approved, loading device data...");
await _loadDeviceData();
timer.cancel();
}
});
_deviceApprovalTimer = Timer.periodic(
const Duration(seconds: 5),
(timer) async {
SimpleLogger().info("Checking whether device has been approved...");
bool isApproved = await keyDao.checkIsDeviceApproved();
setState(() => _isDeviceApproved = isApproved);
if (isApproved) {
SimpleLogger().info("Device is approved, loading device data...");
await _loadDeviceData();
timer.cancel();
}
},
);
} else {
SimpleLogger().info("Device is approved, loading device data...");
await _loadDeviceData();
Expand Down Expand Up @@ -109,6 +113,7 @@ class _DefaultScreenState extends State<DefaultScreen> {
@override
void dispose() {
_pageStreamSubscription.cancel();
_deviceApprovalTimer?.cancel();
super.dispose();
}

Expand Down
2 changes: 2 additions & 0 deletions lib/screens/device_setup_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class _DeviceSetupState extends State<DeviceSetupScreen> {
Future<void> _createDevice(DeviceRequest deviceRequest) async {
DevicesApi devicesApi = await apiFactory.getDevicesApi();
try {
SimpleLogger().info(
"Creating device with serial number: ${deviceRequest.serialNumber}");
Device createdDevice =
(await devicesApi.createDevice(deviceRequest: deviceRequest)).data!;
SimpleLogger().info("Created device: $createdDevice");
Expand Down
57 changes: 30 additions & 27 deletions lib/screens/page_screen.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "dart:async";
import "package:defer_pointer/defer_pointer.dart";
import "package:flutter/material.dart";
import "package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart";
import "package:noheva_api/noheva_api.dart";
Expand Down Expand Up @@ -91,34 +92,36 @@ class PageScreenState extends NohevaScreenState<PageScreen> {
textDirection: TextDirection.ltr,
child: Scaffold(
backgroundColor: const Color(0xffffffff),
body: Container(
width: screenSize.width,
height: screenSize.height,
child: HtmlWidget(
_pageHtml ?? "",
customWidgetBuilder: (element) => HtmlWidgets.buildCustomWidget(
element,
_pageResources,
_eventTriggers,
_enterTransitions,
_exitTransitions,
context,
),
customStylesBuilder: (element) {
if (["h1", "h2", "h3", "h4", "h5", "h6"]
.contains(element.localName)) {
return {
"font-family": "Larken-Medium",
};
}
if (element.localName == "p") {
return {
"font-family": "Source-Sans-Pro-Regular",
};
}
body: DeferredPointerHandler(
child: Container(
width: screenSize.width,
height: screenSize.height,
child: HtmlWidget(
_pageHtml ?? "",
customWidgetBuilder: (element) => HtmlWidgets.buildCustomWidget(
element,
_pageResources,
_eventTriggers,
_enterTransitions,
_exitTransitions,
context,
),
customStylesBuilder: (element) {
if (["h1", "h2", "h3", "h4", "h5", "h6"]
.contains(element.localName)) {
return {
"font-family": "Larken-Medium",
};
}
if (element.localName == "p") {
return {
"font-family": "Source-Sans-Pro-Regular",
};
}

return null;
},
return null;
},
),
),
),
),
Expand Down
31 changes: 31 additions & 0 deletions lib/utils/html_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,37 @@ class HtmlWidgets {
_ => null
};

/// Extracts margin from HTML [element] styles and returns it as an [EdgeInsets]
static EdgeInsets? extractMargin(
dom.Element element,
) {
final marginAttributes =
element.styles.where((style) => style.property.startsWith("margin-"));

return EdgeInsets.only(
top: _parsePixelValueToDouble(
marginAttributes
.firstWhereOrNull((style) => style.property == "margin-top")
?.value,
),
right: _parsePixelValueToDouble(
marginAttributes
.firstWhereOrNull((style) => style.property == "margin-right")
?.value,
),
bottom: _parsePixelValueToDouble(
marginAttributes
.firstWhereOrNull((style) => style.property == "margin-bottom")
?.value,
),
left: _parsePixelValueToDouble(
marginAttributes
.firstWhereOrNull((style) => style.property == "margin-left")
?.value,
),
);
}

/// Extracts color from HTML [element] styles and returns it as an int
static Color? extractColor(
dom.Element element, {
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/navigation_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class NavigationUtils {
noheva_api.ExhibitionPageTransition? enterTransition,
noheva_api.ExhibitionPageTransition? exitTransition,
}) async =>
Navigator.push(
Navigator.pushReplacement(
context,
PageRouteBuilder(
transitionDuration: Duration(
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/page_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class PageController {
styles[key] = value;
}
}
;

String? backgroundImage = styles["background-image"];
if (backgroundImage != null && backgroundImage != "none") {
styles["background-image"] = "url(\"file://$backgroundImage\")";
Expand Down
36 changes: 26 additions & 10 deletions lib/widgets/custom_button.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "dart:io";
import "package:defer_pointer/defer_pointer.dart";
import "package:flutter/material.dart";
import "package:html/dom.dart" as dom;
import "package:noheva_api/noheva_api.dart";
Expand Down Expand Up @@ -30,6 +31,7 @@ class CustomButton extends StatelessWidget {
HtmlWidgets.extractColor(element, property: "background-color");
final size = HtmlWidgets.extractSize(element);
final fontFamily = HtmlWidgets.extractFontFamily(element);
final margin = HtmlWidgets.extractMargin(element);
final tapEvent = HtmlWidgets.handleTapEvent(
element,
eventTriggers,
Expand Down Expand Up @@ -59,17 +61,31 @@ class CustomButton extends StatelessWidget {
);
}

return TextButton(
style: ButtonStyle(
backgroundColor: MaterialStatePropertyAll(backgroundColor),
maximumSize: MaterialStatePropertyAll(size),
minimumSize: MaterialStatePropertyAll(size),
shape: MaterialStatePropertyAll(
HtmlWidgets.extractBorderRadius(element),
),
return Container(
constraints: BoxConstraints.loose((size)),
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned(
top: (margin?.vertical ?? 0) / 2,
left: (margin?.horizontal ?? 0) / 2,
child: DeferPointer(
child: TextButton(
style: ButtonStyle(
backgroundColor: MaterialStatePropertyAll(backgroundColor),
maximumSize: MaterialStatePropertyAll(size),
minimumSize: MaterialStatePropertyAll(size),
shape: MaterialStatePropertyAll(
HtmlWidgets.extractBorderRadius(element),
),
),
onPressed: tapEvent,
child: child,
),
),
),
],
),
onPressed: tapEvent,
child: child,
);
}
}
2 changes: 1 addition & 1 deletion noheva-api-spec
Submodule noheva-api-spec updated 1 files
+1 −0 swagger.yaml
2 changes: 1 addition & 1 deletion noheva-api/lib/src/model/device_page_resource.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ abstract class DevicePageResource implements Built<DevicePageResource, DevicePag

@BuiltValueField(wireName: r'type')
ExhibitionPageResourceType get type;
// enum typeEnum { text, image, video, html, svg, };
// enum typeEnum { text, image, video, html, svg, color, };

/// Name of the layout component this resource is attached to.
@BuiltValueField(wireName: r'component')
Expand Down
2 changes: 1 addition & 1 deletion noheva-api/lib/src/model/exhibition_page_resource.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ abstract class ExhibitionPageResource implements Built<ExhibitionPageResource, E

@BuiltValueField(wireName: r'type')
ExhibitionPageResourceType get type;
// enum typeEnum { text, image, video, html, svg, };
// enum typeEnum { text, image, video, html, svg, color, };

ExhibitionPageResource._();

Expand Down
2 changes: 2 additions & 0 deletions noheva-api/lib/src/model/exhibition_page_resource_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class ExhibitionPageResourceType extends EnumClass {
static const ExhibitionPageResourceType html = _$html;
@BuiltValueEnumConst(wireName: r'svg')
static const ExhibitionPageResourceType svg = _$svg;
@BuiltValueEnumConst(wireName: r'color')
static const ExhibitionPageResourceType color = _$color;

static Serializer<ExhibitionPageResourceType> get serializer => _$exhibitionPageResourceTypeSerializer;

Expand Down
Loading

0 comments on commit 16401ba

Please sign in to comment.