diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 4935ac8..3f05bdb 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + android:versionName="0.0.2"> diff --git a/android/app/src/main/java/com/dinect/checker/activity/CameraActivity.java b/android/app/src/main/java/com/dinect/checker/activity/CameraActivity.java index 12215a3..add943a 100644 --- a/android/app/src/main/java/com/dinect/checker/activity/CameraActivity.java +++ b/android/app/src/main/java/com/dinect/checker/activity/CameraActivity.java @@ -20,6 +20,7 @@ import android.widget.Button; import android.graphics.Rect; import android.support.v7.widget.Toolbar; import android.hardware.Camera; +import android.hardware.Camera.CameraInfo; import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.Parameters; @@ -39,10 +40,15 @@ import net.sourceforge.zbar.SymbolSet; import net.sourceforge.zbar.Config; import android.graphics.YuvImage; import android.view.MenuItem; - +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import java.io.IOException; +import java.util.List; import com.dinect.checker.R; -public class CameraActivity extends AppCompatActivity { +public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback { private Camera mCamera; private Handler mAutoFocusHandler = new Handler(); @@ -56,6 +62,17 @@ public class CameraActivity extends AppCompatActivity { System.loadLibrary("iconv"); } + /** A safe way to get an instance of the Camera object. */ + private static Camera getCameraInstance(){ + Camera c = null; + try { + c = Camera.open(); + } catch (Exception e){ + e.printStackTrace(); + } + return c; + } + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.a_scanner); @@ -74,34 +91,102 @@ public class CameraActivity extends AppCompatActivity { } mCamera = getCameraInstance(); - mCamera.setDisplayOrientation(90); + mCamera.setPreviewCallback(previewCallback); - holder.addCallback(new SurfaceHolder.Callback() { - @Override - public void surfaceCreated(SurfaceHolder holder) { - try { + Camera.Parameters params = mCamera.getParameters(); + List focusModes = params.getSupportedFocusModes(); + for (String fMode : focusModes) { + Log.d("kifio", fMode); + } + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); + } + mCamera.setParameters(params); - mCamera.setPreviewDisplay(holder); - mCamera.startPreview(); - mCamera.setPreviewCallback(previewCallback); - mCamera.autoFocus(autoFocusCB); - initCountours(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - - } - }); + holder.addCallback(this); } + @Override + protected void onResume() { + super.onResume(); + mCamera.startPreview(); + } + + @Override + protected void onPause() { + super.onPause(); + mCamera.stopPreview(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mCamera != null) + mCamera.release(); + mCamera = null; + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + try { + mCamera.setPreviewDisplay(holder); + Log.d("kifio", "surfaceCreated"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + setCameraDisplayOrientation(0); + Log.d("kifio", "surfaceChanged"); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + Log.d("kifio", "surfaceDestroyed"); + } + + void setCameraDisplayOrientation(int cameraId) { + + int rotation = getWindowManager().getDefaultDisplay().getRotation(); + int degrees = 0; + switch (rotation) { + case Surface.ROTATION_0: + degrees = 0; + break; + case Surface.ROTATION_90: + degrees = 90; + break; + case Surface.ROTATION_180: + degrees = 180; + break; + case Surface.ROTATION_270: + degrees = 270; + break; + } + + int result = 0; + + // получаем инфо по камере cameraId + CameraInfo info = new CameraInfo(); + Camera.getCameraInfo(cameraId, info); + + // задняя камера + if (info.facing == CameraInfo.CAMERA_FACING_BACK) { + result = ((360 - degrees) + info.orientation); + } else + // передняя камера + if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { + result = ((360 - degrees) - info.orientation); + result += 360; + } + result = result % 360; + mCamera.setDisplayOrientation(result); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); @@ -124,13 +209,6 @@ public class CameraActivity extends AppCompatActivity { finish(); } - @Override - public void onDestroy() { - super.onDestroy(); - mCamera = null; - } - - private void initCountours() { DisplayMetrics displayMetrics = new DisplayMetrics(); @@ -143,43 +221,12 @@ public class CameraActivity extends AppCompatActivity { mContours.put("width", (int) res.getDimension(R.dimen.scanner_contour_height)); mContours.put("height", width - (2 * (int) res.getDimension(R.dimen.scanner_contour_left))); - Log.d("kifio", "left: " + mContours.get("left")); - Log.d("kifio", "top: " + mContours.get("top")); - Log.d("kifio", "width: " + mContours.get("width")); - Log.d("kifio", "height: " + mContours.get("height")); + // Log.d("kifio", "left: " + mContours.get("left")); + // Log.d("kifio", "top: " + mContours.get("top")); + // Log.d("kifio", "width: " + mContours.get("width")); + // Log.d("kifio", "height: " + mContours.get("height")); } - public void onPause() { - super.onPause(); - releaseCamera(); - } - - /** A safe way to get an instance of the Camera object. */ - public static Camera getCameraInstance(){ - Camera c = null; - try { - c = Camera.open(); - } catch (Exception e){ - } - return c; - } - - private void releaseCamera() { - if (mCamera != null) { - previewing = false; - mCamera.setPreviewCallback(null); - mCamera.release(); - mCamera = null; - } - } - - private Runnable doAutoFocus = new Runnable() { - public void run() { - if (previewing) - mCamera.autoFocus(autoFocusCB); - } - }; - PreviewCallback previewCallback = new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera camera) { @@ -204,16 +251,8 @@ public class CameraActivity extends AppCompatActivity { intent.putExtra("code", sym.getData()); setResult(RESULT_OK, intent); finish(); - Toast.makeText(CameraActivity.this, sym.getData(), Toast.LENGTH_SHORT).show(); } } } }; - - // Mimic continuous auto-focusing - AutoFocusCallback autoFocusCB = new AutoFocusCallback() { - public void onAutoFocus(boolean success, Camera camera) { - mAutoFocusHandler.postDelayed(doAutoFocus, 1000); - } - }; } \ No newline at end of file diff --git a/android/app/src/main/res/layout/a_scanner.xml b/android/app/src/main/res/layout/a_scanner.xml index 4fd7ecc..6ea9cda 100644 --- a/android/app/src/main/res/layout/a_scanner.xml +++ b/android/app/src/main/res/layout/a_scanner.xml @@ -10,7 +10,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"/> - @@ -41,7 +41,7 @@ android:layout_width="match_parent" android:background="#с0000000"/> - + --> { getHintLabel(), getDecoratedTextWidget(), getMessage(), - buildButton(new EdgeInsets.only(top: 36.0, left: buttonVerticalMargin, right: buttonVerticalMargin), - buildRaisedButton(context, _tokenActive ? 'ЗАВЕРШИТЬ РЕГИСТРАЦИЮ' : 'ОБНОВИТЬ СТАТУС АКТИВАЦИИ', () => handleTap())) + buildRaisedButton(context, _tokenActive ? 'ЗАВЕРШИТЬ РЕГИСТРАЦИЮ' : 'ОБНОВИТЬ СТАТУС АКТИВАЦИИ', () => handleTap()) ]); } diff --git a/lib/base_state.dart b/lib/base_state.dart index ad43148..4350068 100644 --- a/lib/base_state.dart +++ b/lib/base_state.dart @@ -46,7 +46,8 @@ abstract class BaseState extends State { String getHint(); faq() { - pushRoute(context, new FAQScreen()); + var route = new MaterialPageRoute(builder: (BuildContext context) => new FAQScreen()); + Navigator.of(context).push(route); } /// Метод возвращает контейнер с отступами, который содержит картинку с логотипом. @@ -101,7 +102,7 @@ abstract class BaseState extends State { /// Метод возвращает BoxDecoration для _getDecoratedInputField getDecoraionForTextWidget() { return new BoxDecoration(color: getTextFilledBackground(), - border: new Border.all(color: textBorderColor, width: 1.0,), + border: new Border.all(color: textBorderColor, width: 1.0), borderRadius: new BorderRadius.all(new Radius.circular(4.0))); } diff --git a/lib/faq.dart b/lib/faq.dart index f6e4bc3..01bf97f 100644 --- a/lib/faq.dart +++ b/lib/faq.dart @@ -11,21 +11,25 @@ class Entry { } class EntryItem extends StatelessWidget { + const EntryItem(this.entry); - final Entry entry; - Widget _buildTiles(Entry root) { - return new ExpansionTile( + Widget _buildTiles(BuildContext context, Entry root) { + EdgeInsets margin = new EdgeInsets.only(left: 20.0, right: 20.0); + TextStyle titleStyle = Theme.of(context).textTheme.button.copyWith(fontWeight: FontWeight.bold, color: faqTitlesColor); + return new Container(margin: margin, child: new Card(child: new ExpansionTile( key: new PageStorageKey(root), - title: new Text(root.title), - children: [new Text(root.text)] - ); + title:new Text(root.title, style: titleStyle), + children: [new Container(margin: margin, padding: new EdgeInsets.only(top: 12.0, bottom: 20.0), + child: new Text(root.text, style: new TextStyle(fontWeight: FontWeight.w300, color: faqGrey, fontSize: 14.0)), + decoration: new BoxDecoration(border: new Border(top: new BorderSide(color: greyTextColor, width: 0.5))))] + ))); } @override Widget build(BuildContext context) { - return _buildTiles(entry); + return _buildTiles(context, entry); } } @@ -34,10 +38,10 @@ class FAQScreen extends StatelessWidget { AppBar getAppBar(BuildContext context) { return new AppBar(title: new Text('FAQ', style: new TextStyle(fontSize: 18.0)), - backgroundColor: primaryColor, actions: [getLogoutButton()]); + backgroundColor: primaryColor, actions: [getLogoutButton(context)]); } - getLogoutButton() { + getLogoutButton(BuildContext context) { return new IconButton(icon: new Image.asset(logout_png, height: iconHeight, width: iconHeight), onPressed: () => logout(context)); } @override @@ -54,10 +58,10 @@ class FAQScreen extends StatelessWidget { /// Список с контентом final List data = [ - new Entry('Регистрация', registrationGuide), - new Entry('Использование', usageGuide), - new Entry('Контакты поддержки', supportGuide), - new Entry('Использование', commonGuide) + new Entry('РЕГИСТРАЦИЯ', registrationGuide), + new Entry('ИСПОЛЬЗОВАНИЕ', usageGuide), + new Entry('КОНТАКТЫ ПОДДЕРЖКИ', supportGuide), + new Entry('ОБЩАЯ ИНФОРМАЦИЯ', commonGuide) ]; /// TODO: Отформатировать строки diff --git a/lib/main.dart b/lib/main.dart index b5734ac..38c3e82 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -23,7 +23,9 @@ const String splash_png = 'assets/splash.png'; const String logout_png = 'assets/logout.png'; const String activate_token_bg_png = 'assets/activate_token_message_background.png'; const String active_token_bg_png = 'assets/active_token_message_background.png'; - +const String expansion_icon_png = 'assets/expansion_icon.png'; +const String powered_by_dinect_splash_png = 'assets/powered_by_dinect_splash.png'; +const String powered_by_dinect_png = 'assets/powered_by_dinect.png'; // Colors const Color primaryColor = const Color(0xffeb0004); const Color greyTextColor = const Color(0xffa5a5a5); @@ -31,7 +33,8 @@ const Color textBorderColor = const Color(0xffcfd8dc); const Color tokenActiveTextColor = const Color(0xff1f5a1f); const Color tokenActivateTextColor = const Color(0xff4e3a19); const Color greenBackground = const Color(0xff8ae28a); - +const Color faqGrey = const Color(0xff5b5b5b); +const Color faqTitlesColor = const Color(0xff404040); // Dimens const double verticalMargin = 28.0; const double buttonVerticalMargin = 42.0; @@ -62,44 +65,68 @@ startScanner(BuildContext context) async { // Канал ловит вызовы методов из "нативной" части приложения. // Могут быть вызваны либо logaut либо faq, либо purchase. - platform.setMethodCallHandler((MethodCall call) async { - - if (call.method == 'foo') { - logout(context); - } else { - pushRoute(context, new PurchaseScreen()); - } + if (token != null) { + platform.setMethodCallHandler((MethodCall call) async { - return result; + if (call.method == 'foo') { + logout(context); + } else { - }); + var card = call.arguments; + + print('card: ' + card); + String url = 'http://pos-api-int.dinect.com/20130701/users/?auto=${card}'; + print('url: ' + url); + + var headers = { + 'DM-Authorization': 'dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08', + 'Authorization': 'dmtoken ${token}' + }; + + httpClient.get(url, headers: headers).then((response) { + + print(response.body); + + List usersList = JSON.decode(response.body); + + if (usersList.length > 0) { + pushRoute(context, new PurchaseScreen(usersList[0], card)); + } + + }).catchError((error) { + print(error.toString()); + }); + + } + }); + } - Navigator.of(context).pop(); await platform.invokeMethod('startScanner'); } logout(BuildContext context) { - - String url = intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken; - print(url); - httpClient.delete(url).then((response) { - print(response.body); - const platform = const MethodChannel('com.dinect.checker/instance_id'); - platform.invokeMethod('removeKeys'); - pushRoute(context, new RegistrationScreen()); - }).catchError((error) { - print(error.toString()); - }); - + if (token != null) { + String url = intUrl + 'tokens/' + token + '?_dmapptoken=' + intToken; + print(url); + httpClient.delete(url).then((response) { + print(response.body); + const platform = const MethodChannel('com.dinect.checker/instance_id'); + platform.invokeMethod('removeKeys'); + Navigator.of(context).pop(); + pushRoute(context, new RegistrationScreen()); + }).catchError((error) { + print(error.toString()); + }); + } else { + Navigator.of(context).pop(); + } } /// Навигация по приложению. /// widget - следующий экран приложения. pushRoute(BuildContext context, Widget widget) { - Navigator.of(context).pushReplacement(new MaterialPageRoute( - builder: (BuildContext context) { - return widget; - })); + var route = new MaterialPageRoute(builder: (BuildContext context) => widget); + Navigator.of(context).pushReplacement(route); } class Checker extends StatelessWidget { @@ -111,4 +138,6 @@ class Checker extends StatelessWidget { accentColor: primaryColor )); } -} \ No newline at end of file +} + + diff --git a/lib/purchase.dart b/lib/purchase.dart index aac3a82..b59f014 100644 --- a/lib/purchase.dart +++ b/lib/purchase.dart @@ -9,12 +9,41 @@ import 'purchase_success.dart'; /// Экран проведения покупки. class PurchaseScreen extends StatefulWidget { - @override State createState() => new PurchaseScreenState(); + + PurchaseScreen(this.response, this.card); + + Map response; + String card; + + @override State createState() => new PurchaseScreenState(response, card); } -class PurchaseScreenState extends BaseState { +class PurchaseScreenState extends BaseState { + PurchaseScreenState(Map user, String card) { + this.user = user; + this.card = card; + getLoyality(user['loyalty_url']); + } + + Map user; + String card; String integerPart = '', fractionalPart = ''; + String loyality = ''; + + @override Widget getScreenContent() { + return new Container(height: 412.0, + child: new ListView(reverse: true, children: [ + new Column(children: [ + getValueWithTitle('ФИО', user['first_name']), + getValueWithTitle('Карта', card), + getValueWithTitle('Вознаграждение', loyality), + getHintLabel(), + getDecoratedTextWidget(), + buildButton(new EdgeInsets.only(top: 36.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildRaisedButton(context, 'ЗАВЕРШИТЬ ПОКУПКУ', () => _purchase(context))), + buildButton(new EdgeInsets.only(top: 24.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildFlatButton(context, 'СКАНИРОВАТЬ', primaryColor))]) + ].reversed.toList())); + } @override String getTitle() { return "Проведение покупки"; @@ -25,24 +54,7 @@ class PurchaseScreenState extends BaseState { } @overide getMenuButtons(BuildContext context) { - return [ - new getFaqButton(), - new getLogoutButton() - ]; - } - - @override Widget getScreenContent() { - return new Container(height: 412.0, - child: new ListView(reverse: true, children: [ - new Column(children: [ - getValueWithTitle('ФИО', 'Знаменитый Рокер Паук'), - getValueWithTitle('Карта', 'B0399900702'), - getValueWithTitle('Вознаграждение', '100%'), - getHintLabel(), - getDecoratedTextWidget(), - buildButton(new EdgeInsets.only(top: 36.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildRaisedButton(context, 'ЗАВЕРШИТЬ ПОКУПКУ', () => _purchase(context))), - buildButton(new EdgeInsets.only(top: 24.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildFlatButton(context, 'СКАНИРОВАТЬ', primaryColor))]) - ].reversed.toList())); + return [getFaqButton(), getLogoutButton()]; } @override Color getTextFilledBackground() { @@ -71,6 +83,35 @@ class PurchaseScreenState extends BaseState { }); } + getLoyality(String url) { + + var headers = { + 'DM-Authorization': 'dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08', + 'Authorization': 'dmtoken ${token}' + }; + + httpClient.get(url, headers: headers).then((response) { + + print(response.body); + + Map bonuses = JSON.decode(response.body); + String type = bonuses['type']; + + setState(() { + if (type == 'amount') { + this.loyality = user['discount']; + } else { + List bonusToAmount = bonuses['bonus_to_amount']; + this.loyality = (bonusToAmount[1].toInt() / bonusToAmount[0].toInt() ).toString(); + } + }); + + }).catchError((error) { + print(error.toString()); + }); + + } + _buildSum() { String temporaryInteger = integerPart; String temporaryFractional = fractionalPart; @@ -84,6 +125,7 @@ class PurchaseScreenState extends BaseState { _purchase(BuildContext context) { String val = _buildSum(); + print(val); showDialog(context: context, child: new AlertDialog( title: new Text('Подтверждение'), content: new Text('Вы подтверждаете покупку на ${val} руб?'), @@ -97,7 +139,8 @@ class PurchaseScreenState extends BaseState { new FlatButton( child: new Text('Да'), onPressed: () { - pushRoute(context, new PurchaseSuccessScreen(val)); + Navigator.of(context).pop(); + pushRoute(context, new PurchaseSuccessScreen(val, user['first_name'])); }, ) ])); diff --git a/lib/purchase_success.dart b/lib/purchase_success.dart index 67600e5..2903b02 100644 --- a/lib/purchase_success.dart +++ b/lib/purchase_success.dart @@ -8,21 +8,22 @@ import 'purchase.dart'; /// Экран проведения покупки. class PurchaseSuccessScreen extends StatefulWidget { - String val = ''; + PurchaseSuccessScreen(this.val, this.name); + String val; + String name; - PurchaseSuccessScreen(String val) { - this.val = val; - } - - @override State createState() => new PurchaseSuccessScreenState(val); + @override State createState() => new PurchaseSuccessScreenState(val, name); } -class PurchaseSuccessScreenState extends PurchaseScreenState { +class PurchaseSuccessScreenState extends BaseState { - String val = ''; + PurchaseSuccessScreenState(this.sum, this.username); - PurchaseSuccessScreenState(String val) { - this.val = val; + String sum; + String username; + + @overide getMenuButtons(BuildContext context) { + return [getFaqButton(), getLogoutButton()]; } @override String getTitle() { @@ -31,7 +32,7 @@ class PurchaseSuccessScreenState extends PurchaseScreenState { @override Widget getScreenContent() { return new Column(children: [ - getValueWithTitle('Покупатель', 'Знаменитый Рокер Паук'), + getValueWithTitle('Покупатель', username), getSuccessMessage(), new Expanded(child: new Center()), buildButton(new EdgeInsets.only(bottom: 74.0, left: buttonVerticalMargin, right: buttonVerticalMargin), buildRaisedButton(context, 'СКАНИРОВАТЬ', () => startScanner(context))) @@ -41,7 +42,7 @@ class PurchaseSuccessScreenState extends PurchaseScreenState { getSuccessMessage() { return new Row(children: [new Expanded(child: new Container(margin: new EdgeInsets.only(top: 20.0), height: 64.0, decoration: new BoxDecoration(color: greenBackground), - child: new Center(child: new Text('Покупка на сумму ${val} руб. проведена', textAlign: TextAlign.center, + child: new Center(child: new Text('Покупка на сумму ${sum} руб. проведена', textAlign: TextAlign.center, style: new TextStyle(fontWeight: FontWeight.bold, color: tokenActiveTextColor)))))]); } diff --git a/lib/registration.dart b/lib/registration.dart index 54a0dee..29a675d 100644 --- a/lib/registration.dart +++ b/lib/registration.dart @@ -33,8 +33,7 @@ class _RegistrationScreenState extends BaseState { getLogo(), getHintLabel(), getDecoratedTextWidget(), - buildButton(new EdgeInsets.only(top: 36.0, left: buttonVerticalMargin, right: buttonVerticalMargin), - buildRaisedButton(context, 'ЗАРЕГИСТРИРОВАТЬ', _isValidMerchantID() && !loading ? () => _registerShop(context) : null))])) + new Container(margin: new EdgeInsets.only(top: 36.0), child: buildRaisedButton(context, 'ЗАРЕГИСТРИРОВАТЬ', _isValidMerchantID() && !loading ? () => _registerShop(context) : null))])) ].reversed.toList())); } diff --git a/lib/splash.dart b/lib/splash.dart index ac8128f..2acbf8b 100644 --- a/lib/splash.dart +++ b/lib/splash.dart @@ -16,9 +16,18 @@ class SplashScreen extends StatelessWidget { // Появляется splash screen, проверяется токен. new Future.delayed(const Duration(milliseconds: 500), () { showNextScreen(context); + // startScanner(context); + // pushRoute(context, new PurchaseScreen(null)); }); - return new Image.asset(splash_png, fit: BoxFit.cover); + return new Stack(children: [new Container(padding: new EdgeInsets.only(left: 48.0, right: 48.0), decoration: getSplashBg()), + new Align(alignment: FractionalOffset.bottomRight, child: + new Container(margin: new EdgeInsets.only(right: 11.0, bottom: 5.0), child: new Image.asset(powered_by_dinect_splash_png, height: 16.0, width: 122.0)))]); + } + + Decoration getSplashBg() { + return new BoxDecoration(image: new DecorationImage( + image: new ExactAssetImage(splash_png), fit: BoxFit.cover)); } /// Запуск следующего экрана приложения. diff --git a/pubspec.yaml b/pubspec.yaml index 3d2d690..011ab7c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,11 @@ flutter: - assets/logout.png - assets/activate_token_message_background.png - assets/active_token_message_background.png + - assets/expansion_icon.png + - assets/powered_by_dinect_splash.png + - assets/powered_by_dinect.png + + # To add assets from package dependencies, first ensure the asset # is in the lib/ directory of the dependency. Then,