Skip to content
Snippets Groups Projects
Commit 5ca37707 authored by vjrj's avatar vjrj
Browse files

Another hackathon

parent 22d2e460
No related branches found
No related tags found
No related merge requests found
Showing
with 437 additions and 121 deletions
...@@ -7,7 +7,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ ...@@ -7,7 +7,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
apt-get clean apt-get clean
ARG GINKGO_WEB_VERSION=0.0.9 ARG GINKGO_WEB_VERSION=0.0.12
ARG GINKGO_WEB_VERSION_PATH=176d988bc6e5c3756973cef2038c7d6c ARG GINKGO_WEB_VERSION_PATH=176d988bc6e5c3756973cef2038c7d6c
RUN curl -L https://git.duniter.org/vjrj/ginkgo/uploads/${GINKGO_WEB_VERSION_PATH}/ginkgo-web-${GINKGO_WEB_VERSION}.tgz | tar xfz - -C /usr/share/nginx/html/ --strip-components=2 RUN curl -L https://git.duniter.org/vjrj/ginkgo/uploads/${GINKGO_WEB_VERSION_PATH}/ginkgo-web-${GINKGO_WEB_VERSION}.tgz | tar xfz - -C /usr/share/nginx/html/ --strip-components=2
...@@ -27,12 +27,11 @@ COPY assets/img/ /usr/share/nginx/html/assets/img/ ...@@ -27,12 +27,11 @@ COPY assets/img/ /usr/share/nginx/html/assets/img/
# Copy the default nginx configuration and g1nkgo conf to restore in empty volumes # Copy the default nginx configuration and g1nkgo conf to restore in empty volumes
RUN cp -a /etc/nginx/ /etc/nginx-default/ RUN cp -a /etc/nginx/ /etc/nginx-default/
# Copy startup.sh (copy previous assets if people mount empty volumes)
COPY startup.sh /usr/local/bin/startup.sh
RUN chmod +x /usr/local/bin/startup.sh
# Exponer los puertos de nginx # Exponer los puertos de nginx
EXPOSE 80 EXPOSE 80
EXPOSE 443 EXPOSE 443
CMD ["nginx", "-g", "daemon off;"] COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
...@@ -5,11 +5,11 @@ SENTRY_DSN=https://306345cb87ee4e1cbbe9023fb4afc5fc@sentry.comunes.org/6 ...@@ -5,11 +5,11 @@ SENTRY_DSN=https://306345cb87ee4e1cbbe9023fb4afc5fc@sentry.comunes.org/6
CARD_COLOR_LEFT=0xFF598040 CARD_COLOR_LEFT=0xFF598040
CARD_COLOR_RIGHT=0xFF225500 CARD_COLOR_RIGHT=0xFF225500
# Empty for default # Empty for default
CARD_COLOR_TEXT=Ğ1 Wallet Dev CARD_TEXT=Ğ1 Wallet Dev
# Nodes space-separated # Nodes space-separated
# The duniter nodes are only used at boot time, later it tries to calculate periodically the nodes # The duniter nodes are only used at boot time, later it tries to calculate periodically the nodes
# that are available with the less latency # that are available with the less latency
DUNITER_NODES=https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr https://g1.monnaielibreoccitanie.org https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr DUNITER_NODES=https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr https://g1.monnaielibreoccitanie.org https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr
CESIUM_PLUS_NODES=https://g1.data.le-sou.org https://g1.data.e-is.pro https://g1.data.presler.fr https://g1.data.mithril.re CESIUM_PLUS_NODES=https://g1.data.le-sou.org https://g1.data.e-is.pro https://g1.data.presler.fr https://g1.data.mithril.re
GVA_NODES=https://g1v1.p2p.legal:443/gva https://g1.asycn.io:443/gva https://duniter.pini.fr:443/gva https://duniter.cuates.net:443/gva GVA_NODES=https://g1v1.p2p.legal:443/gva https://g1.asycn.io:443/gva https://duniter.pini.fr:443/gva
SENTRY_DSN=https://306345cb87ee4e1cbbe9023fb4afc5fc@sentry.comunes.org/6 SENTRY_DSN=https://306345cb87ee4e1cbbe9023fb4afc5fc@sentry.comunes.org/6
# Card customization # Card customization
CARD_COLOR_LEFT=0xFF05112B CARD_COLOR_LEFT="0xFF05112B"
CARD_COLOR_RIGHT=0xFF085476 CARD_COLOR_RIGHT="0xFF085476"
# Empty for default # Empty for default
CARD_COLOR_TEXT=Ğ1 Wallet CARD_TEXT=Ğ1 Wallet
# Nodes space-separated # Nodes space-separated
# The duniter nodes are only used at boot time, later it tries to calculate periodically the nodes # The duniter nodes are only used at boot time, later it tries to calculate periodically the nodes
# that are available with the less latency # that are available with the less latency
DUNITER_NODES=https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr https://g1.monnaielibreoccitanie.org https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr DUNITER_NODES=http://192.168.32.3:10901 https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr https://g1.monnaielibreoccitanie.org https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr
CESIUM_PLUS_NODES=https://g1.data.le-sou.org https://g1.data.e-is.pro https://g1.data.presler.fr https://g1.data.mithril.re CESIUM_PLUS_NODES=https://g1.data.le-sou.org https://g1.data.e-is.pro https://g1.data.presler.fr https://g1.data.mithril.re
GVA_NODES=https://g1v1.p2p.legal:443/gva https://g1.asycn.io:443/gva https://duniter.pini.fr:443/gva https://duniter.cuates.net:443/gva GVA_NODES=https://g1v1.p2p.legal:443/gva https://g1.asycn.io:443/gva https://duniter.pini.fr:443/gva
version: '3' version: '3'
services: services:
duniter:
container_name: duniter
environment:
- DEBUG_ENTRYPOINT=${DUNITER_DEBUG_ENTRYPOINT:-${DEBUG_ENTRYPOINT:-${DEBUG:-}}}
- DUNITER_AUTO_SYNC=${DUNITER_AUTO_SYNC:-true}
- DUNITER_BMA_ENABLED=${DUNITER_BMA_ENABLED:-true}
- DUNITER_BMA_IP4=${DUNITER_BMA_IP4:-0.0.0.0}
- DUNITER_BMA_REMOTE_HOST=${DUNITER_BMA_REMOTE_HOST:-duniter.localhost}
- DUNITER_BMA_REMOTE_PORT=${DUNITER_BMA_REMOTE:-443}
- DUNITER_GVA_ENABLED=${DUNITER_GVA_ENABLED:-true}
- DUNITER_GVA_PATH=${DUNITER_GVA_PATH:-gva}
- DUNITER_GVA_PORT=${DUNITER_GVA_PORT:-30901}
- DUNITER_GVA_REMOTE_HOST=${DUNITER_GVA_REMOTE_HOST:-duniter.localhost}
- DUNITER_GVA_REMOTE_PATH=${DUNITER_GVA_REMOTE_PATH:-gva}
- DUNITER_GVA_REMOTE_PORT=${DUNITER_GVA_REMOTE_PORT:-443}
- DUNITER_GVA_REMOTE_TLS=${DUNITER_GVA_REMOTE_TLS:-false}
- DUNITER_GVA_WHITELIST=${DUNITER_GVA_WHITELIST:-127.0.0.1,::1}
- DUNITER_MANUAL_CONFIG=${DUNITER_MANUAL_CONFIG:-false}
- DUNITER_POW_PREFIX=${DUNITER_POW_PREFIX:-}
- DUNITER_POW_CPU=${DUNITER_POW_CPU:-0.8}
- DUNITER_POW_NBCORES=${DUNITER_POW_NBCORES:-1}
- DUNITER_START_OPTS=${DUNITER_START_OPTS:-direct_webstart}
- DUNITER_SYNC_HOST=${DUNITER_SYNC_HOST:-g1.duniter.org:443}
- DUNITER_SYNC_OPTS=${DUNITER_SYNC_OPTS:-}
- DUNITER_WS2P_HOST=${DUNITER_WS2P_HOST:-0.0.0.0}
- DUNITER_WS2P_PORT=${DUNITER_W2SP_PORT:-20901}
- DUNITER_WS2P_PUBLIC=${DUNITER_W2SP_PUBLIC:-true}
- DUNITER_WS2P_REMOTE_HOST=${DUNITER_WS2P_REMOTE_HOST:-duniter.localhost}
- DUNITER_WS2P_REMOTE_PATH=${DUNITER_WS2P_REMOTE_PATH:-ws2p}
- DUNITER_WS2P_REMOTE_PORT=${DUNITER_WS2P_REMOTE_PORT:-443}
image: duniter/duniter:dev
networks:
- private
ports:
- 0.0.0.0:10901:10901
- 0.0.0.0:20901:20901
- 0.0.0.0:30901:30901
- 0.0.0.0:9220:9220
restart: unless-stopped
volumes:
- data:/var/lib/duniter
- etc:/etc/duniter
# Don't auto-updated duniter
labels:
- "com.centurylinklabs.watchtower.enable=false"
# We start duniter but adding g1nkgo local IP to the allow list, so we can use GVA without rate limits (in theory)
entrypoint: /bin/sh -c "while ! getent hosts g1nkgo_host > /dev/null 2>&1; do echo 'Waiting for g1nkgo_host...'; sleep 1; done && G1NKGO_IP=`getent hosts g1nkgo_host | awk '{ print $$1 }'` && export DUNITER_GVA_WHITELIST=$$G1NKGO_IP,$${DUNITER_GVA_WHITELIST:-127.0.0.1,::1} && echo $$DUNITER_GVA_WHITELIST && exec /docker-entrypoint.sh"
g1nkgo: g1nkgo:
image: g1nkgo:latest image: g1nkgo:latest
container_name: g1nkgo container_name: g1nkgo
...@@ -12,12 +60,29 @@ services: ...@@ -12,12 +60,29 @@ services:
volumes: volumes:
- ~/.ginkgo/nginx-conf:/etc/nginx/:rw - ~/.ginkgo/nginx-conf:/etc/nginx/:rw
- ./assets:/usr/share/nginx/html/assets:rw - ./assets:/usr/share/nginx/html/assets:rw
labels:
- "com.centurylinklabs.watchtower.enable=true"
networks:
private:
aliases:
- g1nkgo_host
environment: environment:
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# Useful for having logs with local time # Useful for having logs with local time
TZ: "Europe/Copenhagen" - TZ=${TZ:-Europe/Copenhagen}
command: /bin/bash -c "/usr/local/bin/startup.sh && nginx -g 'daemon off;'" # Sentry conf
# SENTRY_DSN=https://306345cb87ee4e1cbbe9023fb4afc5fc@sentry.comunes.org/6
# Card customization
# Empty for default
- CARD_TEXT=${CARD_TEXT:-Ğ1 Wallet}
# Nodes space-separated
# The duniter nodes are only used at boot time, later it tries to calculate periodically the nodes
# that are available with the less latency
# SENTRY_DSN no tiene valor predeterminado, por lo que no se incluye aquí.
- DUNITER_NODES=${DUNITER_NODES:-https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr https://g1.monnaielibreoccitanie.org https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr}
- CESIUM_PLUS_NODES=${CESIUM_PLUS_NODES:-https://g1.data.le-sou.org https://g1.data.e-is.pro https://g1.data.presler.fr https://g1.data.mithril.re}
- GVA_NODES=${GVA_NODES:-https://g1v1.p2p.legal:443/gva https://g1.asycn.io:443/gva https://duniter.pini.fr:443/gva https://duniter.cuates.net:443/gva}
watchtower: watchtower:
image: containrrr/watchtower image: containrrr/watchtower
...@@ -27,3 +92,16 @@ services: ...@@ -27,3 +92,16 @@ services:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
# Additional watchtower args # Additional watchtower args
# commmand: # commmand:
networks:
- private
networks:
private:
name: ${DOCKER_NETWORK_PRIVATE:-duniter}
# Not in use
# public:
# name: ${DOCKER_NETWORK_PUBLIC:-host}
volumes:
data:
etc:
#!/bin/bash
if [ -z "$(ls -A /etc/nginx)" ]; then
cp -a /etc/nginx-default/* /etc/nginx/
fi
CONFIG_FILE="/usr/share/nginx/html/assets/env.production.txt"
VARIABLES=(
"SENTRY_DSN"
"CARD_TEXT"
"DUNITER_NODES"
"CESIUM_PLUS_NODES"
"GVA_NODES"
)
DUNITER_IP=$(getent hosts duniter | awk '{ print $1 }')
export GVA_NODES="http://$DUNITER_IP:30901 ${GVA_NODES}"
for VAR_NAME in "${VARIABLES[@]}"; do
VAR_VALUE=${!VAR_NAME}
if [ ! -z "$VAR_VALUE" ]; then
ESCAPED_VAR_VALUE=$(echo "$VAR_VALUE" | sed -e 's/[\/&]/\\&/g')
sed -i -e "s/^\($VAR_NAME=\).*\$/\1$ESCAPED_VAR_VALUE/" $CONFIG_FILE
fi
done
exec nginx -g "daemon off;"
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
<string>es</string> <string>es</string>
<string>fr</string> <string>fr</string>
<string>ca</string> <string>ca</string>
<string>de</string>
<string>nl</string>
</array> </array>
<key>LSApplicationQueriesSchemes</key> <key>LSApplicationQueriesSchemes</key>
<array> <array>
......
...@@ -7,7 +7,6 @@ import 'package:flutter/material.dart'; ...@@ -7,7 +7,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:ginkgo/ui/contacts_cache.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:introduction_screen/introduction_screen.dart'; import 'package:introduction_screen/introduction_screen.dart';
...@@ -31,6 +30,7 @@ import 'data/models/payment_cubit.dart'; ...@@ -31,6 +30,7 @@ import 'data/models/payment_cubit.dart';
import 'data/models/transaction_cubit.dart'; import 'data/models/transaction_cubit.dart';
import 'g1/api.dart'; import 'g1/api.dart';
import 'shared_prefs.dart'; import 'shared_prefs.dart';
import 'ui/contacts_cache.dart';
import 'ui/logger.dart'; import 'ui/logger.dart';
import 'ui/screens/skeleton_screen.dart'; import 'ui/screens/skeleton_screen.dart';
import 'ui/ui_helpers.dart'; import 'ui/ui_helpers.dart';
...@@ -45,17 +45,17 @@ void main() async { ...@@ -45,17 +45,17 @@ void main() async {
await FlutterDisplayMode.setHighRefreshRate(); await FlutterDisplayMode.setHighRefreshRate();
} }
final SharedPreferencesHelper shared = SharedPreferencesHelper();
await shared.init();
await shared.getWallet();
assert(shared.getPubKey() != null);
// .env // .env
await dotenv.load( await dotenv.load(
fileName: kReleaseMode fileName: kReleaseMode
? 'assets/env.production.txt' ? 'assets/env.production.txt'
: 'assets/.env.development'); : 'assets/.env.development');
final SharedPreferencesHelper shared = SharedPreferencesHelper();
await shared.init();
await shared.getWallet();
assert(shared.getPubKey() != null);
if (kIsWeb) { if (kIsWeb) {
await Hive.initFlutter(); await Hive.initFlutter();
HydratedBloc.storage = await HydratedStorage.build( HydratedBloc.storage = await HydratedStorage.build(
...@@ -81,6 +81,8 @@ void main() async { ...@@ -81,6 +81,8 @@ void main() async {
Locale('es'), Locale('es'),
Locale('fr'), Locale('fr'),
Locale('ca'), Locale('ca'),
Locale('de'),
Locale('nl'),
], ],
fallbackLocale: const Locale('en'), fallbackLocale: const Locale('en'),
useFallbackTranslations: true, useFallbackTranslations: true,
......
...@@ -2,9 +2,12 @@ import 'dart:convert'; ...@@ -2,9 +2,12 @@ import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:durt/durt.dart'; import 'package:durt/durt.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'data/models/cesium_card.dart'; import 'data/models/cesium_card.dart';
import 'data/models/credit_card_themes.dart';
import 'g1/g1_helper.dart'; import 'g1/g1_helper.dart';
import 'ui/logger.dart'; import 'ui/logger.dart';
...@@ -39,6 +42,32 @@ class SharedPreferencesHelper { ...@@ -39,6 +42,32 @@ class SharedPreferencesHelper {
.map((dynamic e) => CesiumCard.fromJson(e as Map<String, dynamic>)) .map((dynamic e) => CesiumCard.fromJson(e as Map<String, dynamic>))
.toList(); .toList();
} }
// Migrate the current pair if exists
await migrateCurrentPair();
}
Future<void> migrateCurrentPair() async {
if (_prefs.containsKey(_seedKey) &&
_prefs.containsKey(_pubKey) &&
cesiumCards.isEmpty) {
final String seed = _prefs.getString(_seedKey)!;
final String pubKey = _prefs.getString(_pubKey)!;
final CesiumCard card = buildCesiumCard(seed: seed, pubKey: pubKey);
addCesiumCard(card);
// Let's do this later
// await _prefs.remove(_seedKey);
// await _prefs.remove(_pubKey);
setCurrentWalletIndex(0);
}
}
CesiumCard buildCesiumCard({required String seed, required String pubKey}) {
return CesiumCard(
seed: seed,
pubKey: pubKey,
theme: CreditCardThemes.theme1,
name: dotenv.env['CARD_TEXT'] ?? tr('g1_wallet'));
} }
void addCesiumCard(CesiumCard cesiumCard) { void addCesiumCard(CesiumCard cesiumCard) {
...@@ -47,8 +76,11 @@ class SharedPreferencesHelper { ...@@ -47,8 +76,11 @@ class SharedPreferencesHelper {
} }
void removeCesiumCard(int index) { void removeCesiumCard(int index) {
cesiumCards.removeAt(index); // Don't allow the last card to be removed
saveCesiumCards(); if (cesiumCards.length > 1) {
cesiumCards.removeAt(index);
saveCesiumCards();
}
} }
Future<void> saveCesiumCards() async { Future<void> saveCesiumCards() async {
...@@ -57,40 +89,62 @@ class SharedPreferencesHelper { ...@@ -57,40 +89,62 @@ class SharedPreferencesHelper {
await _prefs.setString('cesiumCards', json); await _prefs.setString('cesiumCards', json);
} }
/* WIP part */ // Get the wallet from the specified index (default to first wallet)
Future<CesiumWallet> getWallet({int index = 0}) async {
// I'll only use shared prefs for the duniter seed if (cesiumCards.isNotEmpty && index < cesiumCards.length) {
Future<void> _saveString(String key, String value) async { final CesiumCard card = cesiumCards[index];
await _prefs.setString(key, value); return CesiumWallet.fromSeed(seedFromString(card.seed));
} } else {
// Generate a new wallet if no wallets exist
Future<CesiumWallet> getWallet() async {
String? s = _getString(_seedKey);
if (s == null) {
final Uint8List uS = generateUintSeed(); final Uint8List uS = generateUintSeed();
s = seedToString(uS); final String seed = seedToString(uS);
await _saveString(_seedKey, s);
final CesiumWallet wallet = CesiumWallet.fromSeed(uS); final CesiumWallet wallet = CesiumWallet.fromSeed(uS);
logger('Generated public key: ${wallet.pubkey}'); logger('Generated public key: ${wallet.pubkey}');
await _saveString(_pubKey, wallet.pubkey); addCesiumCard(buildCesiumCard(seed: seed, pubKey: wallet.pubkey));
return wallet; return wallet;
} else {
return CesiumWallet.fromSeed(seedFromString(s));
} }
} }
String getPubKey() { // Get the public key from the specified index (default to first wallet)
// At this point should exists String getPubKey({int index = 0}) {
final String? pubKey = _prefs.getString(_pubKey); final CesiumCard card = cesiumCards[index];
return pubKey!; return card.pubKey;
}
List<CesiumCard> get cards => cesiumCards;
static const String _currentWalletIndexKey = 'current_wallet_index';
// Get the current wallet index from shared preferences
int getCurrentWalletIndex() {
return _prefs.getInt(_currentWalletIndexKey) ?? 0;
}
// Set the current wallet index in shared preferences
Future<void> setCurrentWalletIndex(int index) async {
await _prefs.setInt(_currentWalletIndexKey, index);
}
// Select the current wallet and save its index in shared preferences
Future<void> selectCurrentWallet(int index) async {
if (index < cesiumCards.length) {
final CesiumCard card = cesiumCards[index];
await setCurrentWalletIndex(index);
logger('Selected wallet: ${card.pubKey}');
} else {
logger('Invalid wallet index: $index');
}
} }
String? _getString(String key) { // Get the currently selected wallet
return _prefs.getString(key); Future<CesiumWallet> getCurrentWallet() async {
final int index = getCurrentWalletIndex();
return getWallet(index: index);
} }
Future<void> setKeys(String pubKey, String seed) async { @Deprecated('We should remove this in the future when multi-card is enabled')
await _saveString(_seedKey, seed); void setDefaultWallet(CesiumCard defCesiumCard) {
await _saveString(_pubKey, pubKey); cesiumCards[0] = defCesiumCard;
saveCesiumCards();
} }
} }
...@@ -123,7 +123,7 @@ class ContactsCache { ...@@ -123,7 +123,7 @@ class ContactsCache {
if (record != null) { if (record != null) {
final Map<String, dynamic> typedRecord = final Map<String, dynamic> typedRecord =
Map<String, dynamic>.from(record as Map); Map<String, dynamic>.from(record as Map<String, dynamic>);
final DateTime timestamp = final DateTime timestamp =
DateTime.parse(typedRecord['timestamp'] as String); DateTime.parse(typedRecord['timestamp'] as String);
final bool before = DateTime.now().isBefore(timestamp.add(duration)); final bool before = DateTime.now().isBefore(timestamp.add(duration));
......
...@@ -133,7 +133,7 @@ String formatKAmount(BuildContext context, double amount) => ...@@ -133,7 +133,7 @@ String formatKAmount(BuildContext context, double amount) =>
double parseToDoubleLocalized(String locale, String double) => double parseToDoubleLocalized(String locale, String double) =>
NumberFormat.decimalPattern(locale).parse(double).toDouble(); NumberFormat.decimalPattern(locale).parse(double).toDouble();
String getAppVersion() => '0.0.11'; String getAppVersion() => '0.0.12';
String localizeNumber(BuildContext context, double amount) => String localizeNumber(BuildContext context, double amount) =>
NumberFormat.decimalPattern(context.locale.toString()).format(amount); NumberFormat.decimalPattern(context.locale.toString()).format(amount);
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import '../../data/models/cesium_card.dart'; import '../../data/models/cesium_card.dart';
import '../../shared_prefs.dart'; import '../../shared_prefs.dart';
...@@ -9,47 +12,93 @@ class CardDrawer extends StatelessWidget { ...@@ -9,47 +12,93 @@ class CardDrawer extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<CesiumCard> cards = SharedPreferencesHelper().cesiumCards; final List<CesiumCard> cards = SharedPreferencesHelper().cesiumCards;
const ImageIcon g1nkgoIcon = ImageIcon(
return Drawer( AssetImage('img/favicon.png'),
child: Column( size: 24,
children: <Widget>[ );
const SizedBox( return FutureBuilder<PackageInfo>(
height: 200, future: PackageInfo.fromPlatform(),
child: Center( builder: (BuildContext context, AsyncSnapshot<PackageInfo> snapshot) {
child: Text( if (snapshot.hasData) {
'', // 'Drawer Header', return Drawer(
style: TextStyle( child: Column(
fontSize: 24, children: <Widget>[
fontWeight: FontWeight.bold, DrawerHeader(
), /* decoration: BoxDecoration(
), color: Theme.of(context).primaryColor,
), ), */
), child: Column(
Expanded( children: <Widget>[
child: Container( Image.asset(
decoration: const BoxDecoration( 'assets/img/logo.png',
borderRadius: BorderRadius.only( fit: BoxFit.scaleDown,
topLeft: Radius.circular(20), height: 80.0,
),
// const SizedBox(height: 20.0),
/* Text(tr('app_name'),
style: const TextStyle(
fontSize: 24.0,
color: Colors.white,
)), */
],
),
), ),
), if (!kReleaseMode)
child: ListView.builder( const SizedBox(
shrinkWrap: true, height: 200,
itemCount: cards.length, child: Center(
itemBuilder: (BuildContext context, int index) { child: Text(
final CesiumCard card = cards[index]; 'Cards',
return InkWell( style: TextStyle(
onTap: () { fontSize: 24,
// SharedPreferencesHelper().selectCesiumCard(person); fontWeight: FontWeight.bold,
Navigator.pop(context); ),
}, ),
child: Text(card.pubKey), ),
); ),
}, if (!kReleaseMode)
), Expanded(
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
),
),
child: ListView.builder(
shrinkWrap: true,
itemCount: cards.length,
itemBuilder: (BuildContext context, int index) {
final CesiumCard card = cards[index];
return InkWell(
onTap: () {
SharedPreferencesHelper()
.selectCurrentWallet(index);
Navigator.pop(context);
},
child: Text(card.pubKey),
);
},
),
),
),
AboutListTile(
icon: g1nkgoIcon,
applicationName: tr('app_name'),
applicationVersion:
'Version: ${snapshot.data!.version} build: ${snapshot.data!.buildNumber}',
applicationIcon: g1nkgoIcon,
applicationLegalese:
'© 2023-${DateTime.now().year} Comunes Association, under AGPLv3',
aboutBoxChildren: const <Widget>[
SizedBox(height: 10.0),
]),
],
), ),
), );
], } else {
), return const Center(child: CircularProgressIndicator());
}
},
); );
} }
} }
...@@ -68,8 +68,14 @@ class _ImportDialogState extends State<ImportDialog> { ...@@ -68,8 +68,14 @@ class _ImportDialogState extends State<ImportDialog> {
keyEncrypted, pattern.join()); keyEncrypted, pattern.join());
final bool? confirm = await confirmImport(context); final bool? confirm = await confirmImport(context);
if (confirm != null && confirm) { if (confirm != null && confirm) {
SharedPreferencesHelper().setKeys( /* SharedPreferencesHelper().addCesiumCard(
keys['pub'] as String, keys['seed'] as String); SharedPreferencesHelper().buildCesiumCard(
pubKey: keys['pub'] as String,
seed: keys['seed'] as String));*/
SharedPreferencesHelper().setDefaultWallet(
SharedPreferencesHelper().buildCesiumCard(
pubKey: keys['pub'] as String,
seed: keys['seed'] as String));
if (!mounted) { if (!mounted) {
return; return;
} }
......
import 'package:flutter/material.dart';
TextStyle cardTextStyle(BuildContext context) {
return TextStyle(
fontFamily: 'SourceCodePro',
// decoration: TextDecoration.underline,
color: Colors.white,
fontSize: MediaQuery.of(context).size.width * 0.06,
fontWeight: FontWeight.bold,
shadows: <Shadow>[
Shadow(
blurRadius: 1,
color: Colors.black.withOpacity(0.7),
offset: const Offset(0, 2),
),
Shadow(
blurRadius: 1,
color: Colors.white.withOpacity(0.5),
offset: const Offset(0, -1),
),
],
);
}
...@@ -6,32 +6,13 @@ import 'package:qr_flutter/qr_flutter.dart'; ...@@ -6,32 +6,13 @@ import 'package:qr_flutter/qr_flutter.dart';
import '../../../shared_prefs.dart'; import '../../../shared_prefs.dart';
import '../../ui_helpers.dart'; import '../../ui_helpers.dart';
import 'card_text_style.dart';
class CreditCard extends StatelessWidget { class CreditCard extends StatelessWidget {
CreditCard({super.key}); CreditCard({super.key});
final String publicKey = SharedPreferencesHelper().getPubKey(); final String publicKey = SharedPreferencesHelper().getPubKey();
TextStyle cardTextStyle(BuildContext context) => TextStyle(
fontFamily: 'SourceCodePro',
// decoration: TextDecoration.underline,
color: Colors.white,
fontSize: MediaQuery.of(context).size.width * 0.06,
fontWeight: FontWeight.bold,
shadows: <Shadow>[
Shadow(
blurRadius: 1,
color: Colors.black.withOpacity(0.7),
offset: const Offset(0, 2),
),
Shadow(
blurRadius: 1,
color: Colors.white.withOpacity(0.5),
offset: const Offset(0, -1),
),
],
);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const double cardRadius = 10.0; const double cardRadius = 10.0;
...@@ -80,7 +61,7 @@ class CreditCard extends StatelessWidget { ...@@ -80,7 +61,7 @@ class CreditCard extends StatelessWidget {
child: FittedBox( child: FittedBox(
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
child: Text( child: Text(
dotenv.env['CARD_COLOR_TEXT'] ?? tr('g1_wallet'), dotenv.env['CARD_TEXT'] ?? tr('g1_wallet'),
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.white,
fontSize: fontSize:
......
import 'package:durt/durt.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import '../../ui_helpers.dart';
import 'card_text_style.dart';
class CreditCardMini extends StatelessWidget {
const CreditCardMini({super.key, required this.wallet});
final CesiumWallet wallet;
@override
Widget build(BuildContext context) {
final String pubKey = wallet.pubkey;
const double cardRadius = 10.0;
final bool bigDevice = bigScreen(context);
final double cardPadding = bigDevice ? 26.0 : 16.0;
return Card(
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(cardRadius),
),
child: AspectRatio(
aspectRatio: 1.58, // Credit cart aspect ratio
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(cardRadius),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey[400]!,
blurRadius: 10.0,
spreadRadius: 1.0,
)
],
gradient: LinearGradient(
begin: Alignment.bottomLeft,
end: Alignment.topRight,
colors: <Color>[
Color(int.parse("${dotenv.env['CARD_COLOR_LEFT']}")),
Color(int.parse("${dotenv.env['CARD_COLOR_RIGHT']}")),
],
),
),
child: Stack(children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(160, 10, 0, 0),
child: Opacity(
opacity: 0.1,
child: Image.asset('assets/img/gbrevedot_alt.png'))),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: EdgeInsets.all(cardPadding),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
dotenv.env['CARD_TEXT'] ?? tr('g1_wallet'),
style: TextStyle(
color: Colors.white,
fontSize:
MediaQuery.of(context).size.width * 0.07,
fontWeight: FontWeight.bold,
),
)),
),
const SizedBox(height: 6.0),
Padding(
padding:
EdgeInsets.symmetric(horizontal: cardPadding),
child: Row(children: <Widget>[
GestureDetector(
onTap: () => showTooltip(
context, '', tr('keys_tooltip')),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text('**** **** ',
style: cardTextStyle(context)))),
FittedBox(
fit: BoxFit.scaleDown,
child: Text(
'${pubKey.substring(0, 4)} ${pubKey.substring(4, 8)}',
style: cardTextStyle(context),
))
])),
if (bigDevice) const SizedBox(height: 6.0),
const SizedBox(height: 18.0),
]),
]),
)));
}
}
...@@ -2,9 +2,10 @@ location ~ ^/proxy/(.*)/(gva(/.*)?)$ { ...@@ -2,9 +2,10 @@ location ~ ^/proxy/(.*)/(gva(/.*)?)$ {
set $proxy_url $1; set $proxy_url $1;
set $proxy_uri $2; set $proxy_uri $2;
# resolver 1.1.1.1; # resolver 1.1.1.1;
add_header 'Access-Control-Allow-Origin' '*'; # Try without this to not open the gva proxy to everyone (without rate limits)
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' 'X-Requested-With'; # add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
# add_header 'Access-Control-Allow-Headers' 'X-Requested-With';
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
......
...@@ -821,7 +821,7 @@ packages: ...@@ -821,7 +821,7 @@ packages:
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
package_info_plus: package_info_plus:
dependency: transitive dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: "8df5ab0a481d7dc20c0e63809e90a588e496d276ba53358afc4c4443d0a00697" sha256: "8df5ab0a481d7dc20c0e63809e90a588e496d276ba53358afc4c4443d0a00697"
......
...@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev ...@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# 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
version: 0.0.11 version: 0.0.12
environment: environment:
sdk: ">=2.17.1 <3.0.0" sdk: ">=2.17.1 <3.0.0"
...@@ -63,6 +63,7 @@ dependencies: ...@@ -63,6 +63,7 @@ dependencies:
once: ^1.5.1 once: ^1.5.1
pattern_lock: ^2.0.0 pattern_lock: ^2.0.0
backdrop: ^0.8.1 backdrop: ^0.8.1
package_info_plus: ^3.0.3
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
...@@ -102,6 +103,7 @@ flutter: ...@@ -102,6 +103,7 @@ flutter:
- assets/img/undraw_intro_5.png - assets/img/undraw_intro_5.png
- assets/img/chip.svg - assets/img/chip.svg
- assets/img/logo.png - assets/img/logo.png
- assets/img/favicon.png
- assets/img/logo-duniter.png - assets/img/logo-duniter.png
- assets/img/logo-cesium.png - assets/img/logo-cesium.png
- assets/tx.json - assets/tx.json
......
#!/bin/bash
if [ -z "$(ls -A /etc/nginx)" ]; then
cp -a /etc/nginx-default/* /etc/nginx/
fi
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment