Adds icon/logo images and a splash screen.
@@ -12,17 +12,22 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".SplashActivity"
|
||||
android:theme="@style/Theme.App.Starting"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Intent filter for viewing/opening content:// URIs with binary/octet-stream MIME type (.monster) -->
|
||||
<intent-filter>
|
||||
|
||||
@@ -58,12 +58,33 @@ public class MainActivity extends AppCompatActivity {
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(R.style.AppTheme);
|
||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||
super.onCreate(savedInstanceState);
|
||||
AppCenterInitializer.init(getApplication());
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
com.google.android.material.appbar.MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||
if (toolbar != null) {
|
||||
setSupportActionBar(toolbar);
|
||||
}
|
||||
|
||||
View appBarLayout = findViewById(R.id.app_bar_layout);
|
||||
BottomNavigationView navView = findViewById(R.id.nav_view);
|
||||
|
||||
View container = findViewById(R.id.container);
|
||||
if (container != null) {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(container, (v, windowInsets) -> {
|
||||
Insets systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
if (appBarLayout != null) {
|
||||
appBarLayout.setPadding(0, systemBars.top, 0, 0);
|
||||
}
|
||||
if (navView != null) {
|
||||
navView.setPadding(0, 0, 0, systemBars.bottom);
|
||||
}
|
||||
return windowInsets;
|
||||
});
|
||||
}
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.majinnaibu.monstercards;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(R.style.AppTheme);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_splash);
|
||||
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
|
||||
if (getIntent() != null) {
|
||||
if (getIntent().getExtras() != null) {
|
||||
intent.putExtras(getIntent().getExtras());
|
||||
}
|
||||
if (getIntent().getAction() != null) {
|
||||
intent.setAction(getIntent().getAction());
|
||||
}
|
||||
if (getIntent().getData() != null) {
|
||||
intent.setData(getIntent().getData());
|
||||
}
|
||||
}
|
||||
startActivity(intent);
|
||||
finish();
|
||||
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
}, 1200);
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,12 @@ import com.majinnaibu.monstercards.utils.Logger;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class CollectionsFragment extends MCFragment {
|
||||
private final CompositeDisposable mDisposables = new CompositeDisposable();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -48,18 +50,35 @@ public class CollectionsFragment extends MCFragment {
|
||||
fab.setOnClickListener(v -> showCreateCollectionDialog());
|
||||
}
|
||||
|
||||
View emptyState = root.findViewById(R.id.empty_state);
|
||||
View emptyStateButton = root.findViewById(R.id.empty_state_button);
|
||||
if (emptyStateButton != null) {
|
||||
emptyStateButton.setOnClickListener(v -> showCreateCollectionDialog());
|
||||
}
|
||||
|
||||
RecyclerView recyclerView = root.findViewById(R.id.collection_list);
|
||||
if (recyclerView != null) {
|
||||
setupRecyclerView(recyclerView);
|
||||
setupRecyclerView(recyclerView, emptyState);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView, @Nullable View emptyState) {
|
||||
Context context = requireContext();
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
|
||||
mDisposables.add(repository.getCollectionsWithCount()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(collections -> {
|
||||
boolean isEmpty = (collections == null || collections.isEmpty());
|
||||
if (emptyState != null) {
|
||||
emptyState.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
|
||||
}, Logger::logError));
|
||||
|
||||
CollectionsRecyclerViewAdapter adapter = new CollectionsRecyclerViewAdapter(
|
||||
context,
|
||||
repository.getCollectionsWithCount(),
|
||||
@@ -155,4 +174,10 @@ public class CollectionsFragment extends MCFragment {
|
||||
NavDirections action = CollectionsFragmentDirections.actionNavigationCollectionsToCollectionDetailFragment(collectionId.toString());
|
||||
Navigation.findNavController(requireView()).navigate(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mDisposables.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ public class DashboardFragment extends MCFragment {
|
||||
if (fab != null) {
|
||||
fab.setOnClickListener(v -> showAddToDashboardOptionsDialog());
|
||||
}
|
||||
if (mHolder.emptyStateButton != null) {
|
||||
mHolder.emptyStateButton.setOnClickListener(v -> showAddToDashboardOptionsDialog());
|
||||
}
|
||||
|
||||
setupRecyclerView(mHolder.list);
|
||||
loadDashboardMonsters();
|
||||
@@ -88,7 +91,16 @@ public class DashboardFragment extends MCFragment {
|
||||
}
|
||||
});
|
||||
if (monsterData != null) {
|
||||
monsterData.observe(getViewLifecycleOwner(), monsters -> mAdapter.submitList(monsters));
|
||||
monsterData.observe(getViewLifecycleOwner(), monsters -> {
|
||||
mAdapter.submitList(monsters);
|
||||
boolean isEmpty = (monsters == null || monsters.isEmpty());
|
||||
if (mHolder.emptyState != null) {
|
||||
mHolder.emptyState.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
if (mHolder.list != null) {
|
||||
mHolder.list.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
|
||||
@@ -301,9 +313,13 @@ public class DashboardFragment extends MCFragment {
|
||||
|
||||
private static class ViewHolder {
|
||||
final RecyclerView list;
|
||||
final View emptyState;
|
||||
final View emptyStateButton;
|
||||
|
||||
ViewHolder(View root) {
|
||||
list = root.findViewById(R.id.list);
|
||||
emptyState = root.findViewById(R.id.empty_state);
|
||||
emptyStateButton = root.findViewById(R.id.empty_state_button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.NavDirections;
|
||||
@@ -38,10 +39,12 @@ import com.majinnaibu.monstercards.utils.Logger;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class LibraryFragment extends MCFragment {
|
||||
private final CompositeDisposable mDisposables = new CompositeDisposable();
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
@@ -52,9 +55,15 @@ public class LibraryFragment extends MCFragment {
|
||||
assert fab != null;
|
||||
setupAddMonsterButton(fab);
|
||||
|
||||
View emptyState = root.findViewById(R.id.empty_state);
|
||||
View emptyStateButton = root.findViewById(R.id.empty_state_button);
|
||||
if (emptyStateButton != null) {
|
||||
emptyStateButton.setOnClickListener(v -> createNewMonster());
|
||||
}
|
||||
|
||||
final RecyclerView recyclerView = root.findViewById(R.id.monster_list);
|
||||
assert recyclerView != null;
|
||||
setupRecyclerView(recyclerView);
|
||||
setupRecyclerView(recyclerView, emptyState);
|
||||
|
||||
return root;
|
||||
}
|
||||
@@ -130,10 +139,21 @@ public class LibraryFragment extends MCFragment {
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView, @Nullable View emptyState) {
|
||||
Context context = requireContext();
|
||||
MonsterRepository repository = this.getMonsterRepository();
|
||||
|
||||
mDisposables.add(repository.getMonsters()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(monsters -> {
|
||||
boolean isEmpty = (monsters == null || monsters.isEmpty());
|
||||
if (emptyState != null) {
|
||||
emptyState.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
|
||||
}, Logger::logError));
|
||||
|
||||
LibraryRecyclerViewAdapter adapter = new LibraryRecyclerViewAdapter(
|
||||
context,
|
||||
repository.getMonsters(),
|
||||
@@ -165,30 +185,31 @@ public class LibraryFragment extends MCFragment {
|
||||
}
|
||||
|
||||
private void setupAddMonsterButton(@NonNull FloatingActionButton fab) {
|
||||
fab.setOnClickListener(view -> {
|
||||
Monster monster = new Monster();
|
||||
monster.name = getString(R.string.default_monster_name);
|
||||
MonsterRepository repository = this.getMonsterRepository();
|
||||
repository.addMonster(monster)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
new DisposableCompletableObserver() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
navigateToEditMonster(monster.id);
|
||||
}
|
||||
fab.setOnClickListener(view -> createNewMonster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
||||
Logger.logError("Error creating monster", e);
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Snackbar.make(view, getString(R.string.snackbar_failed_to_create_monster), Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
private void createNewMonster() {
|
||||
Monster monster = new Monster();
|
||||
monster.name = getString(R.string.default_monster_name);
|
||||
MonsterRepository repository = this.getMonsterRepository();
|
||||
mDisposables.add(repository.addMonster(monster)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeWith(new DisposableCompletableObserver() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
navigateToEditMonster(monster.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
||||
Logger.logError("Error creating monster", e);
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Snackbar.make(view, getString(R.string.snackbar_failed_to_create_monster), Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected void navigateToMonsterDetail(@NonNull UUID monsterId) {
|
||||
@@ -203,4 +224,10 @@ public class LibraryFragment extends MCFragment {
|
||||
action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterId.toString());
|
||||
navController.navigate(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mDisposables.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,166 +5,6 @@
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:fillColor="@color/colorPrimaryDark"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
|
||||
BIN
Android/app/src/main/res/drawable/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
Android/app/src/main/res/drawable/ic_logo.png
Normal file
|
After Width: | Height: | Size: 485 KiB |
BIN
Android/app/src/main/res/drawable/ic_splash_combined.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
Android/app/src/main/res/drawable/ic_splash_logo.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Solid dark red background -->
|
||||
<item android:drawable="@color/colorPrimaryDark" />
|
||||
|
||||
<!-- Centered logo + Spindle's End font text -->
|
||||
<item
|
||||
android:width="280dp"
|
||||
android:height="280dp"
|
||||
android:drawable="@drawable/ic_splash_combined"
|
||||
android:gravity="center" />
|
||||
</layer-list>
|
||||
BIN
Android/app/src/main/res/font/spindles_end.ttf
Normal file
@@ -6,6 +6,25 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light"
|
||||
app:navigationIconTint="@android:color/white"
|
||||
app:titleTextColor="@android:color/white" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="0dp"
|
||||
@@ -20,7 +39,6 @@
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
@@ -29,8 +47,8 @@
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/app_bar_layout"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:navGraph="@navigation/mobile_navigation" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
34
Android/app/src/main/res/layout/activity_splash.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorPrimaryDark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/splash_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:fontFamily="@font/spindles_end"
|
||||
android:text="@string/app_title_splash"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/splash_logo"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/splash_logo"
|
||||
android:layout_width="220dp"
|
||||
android:layout_height="220dp"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:scaleType="fitCenter"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_logo" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -17,6 +17,56 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:listitem="@layout/collection_list_item" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/empty_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/empty_state_logo"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:contentDescription="@string/app_name"
|
||||
app:srcCompat="@drawable/ic_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_state_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/empty_collections_title"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_state_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/empty_collections_subtitle"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/empty_state_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/action_add_collection"
|
||||
app:cornerRadius="20dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_add_collection"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -21,6 +21,56 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:listitem="@layout/card_monster" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/empty_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/empty_state_logo"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:contentDescription="@string/app_name"
|
||||
app:srcCompat="@drawable/ic_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_state_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/empty_dashboard_title"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_state_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/empty_dashboard_subtitle"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/empty_state_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/action_add_to_dashboard"
|
||||
app:cornerRadius="20dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_add_to_dashboard"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -19,6 +19,56 @@
|
||||
tools:context=".MonsterListFragment"
|
||||
tools:listitem="@layout/monster_list_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/empty_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/empty_state_logo"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:contentDescription="@string/app_name"
|
||||
app:srcCompat="@drawable/ic_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_state_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/empty_library_title"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_state_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/empty_library_subtitle"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/empty_state_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/action_add_monster"
|
||||
app:cornerRadius="20dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 42 KiB |
25
Android/app/src/main/res/values-v31/styles.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Base application theme for Android 12+ (API 31+). -->
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorSecondary">@color/colorSecondary</item>
|
||||
<item name="colorSecondaryVariant">@color/colorSecondaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorOnPrimary">#ffffff</item>
|
||||
<item name="colorOnSecondary">#000000</item>
|
||||
|
||||
<item name="android:windowBackground">@color/colorPrimaryDark</item>
|
||||
|
||||
<!-- Android 12+ Splash Screen API -->
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_splash_logo</item>
|
||||
<item name="android:windowSplashScreenBackground">@color/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.App.Starting" parent="AppTheme">
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_splash_logo</item>
|
||||
<item name="android:windowSplashScreenBackground">@color/colorPrimaryDark</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -180,4 +180,12 @@
|
||||
<string name="snackbar_import_binder_success">Imported binder successfully</string>
|
||||
<string name="default_filename_library">MonsterCards Library</string>
|
||||
<string name="default_filename_dashboard">MonsterCards Dashboard</string>
|
||||
|
||||
<string name="empty_dashboard_title">Dashboard is Empty</string>
|
||||
<string name="empty_dashboard_subtitle">Pin monster cards or collections here for quick reference during your tabletop sessions.</string>
|
||||
<string name="empty_collections_title">No Collections Yet</string>
|
||||
<string name="empty_collections_subtitle">Organize your monsters into custom campaign or encounter collections.</string>
|
||||
<string name="empty_library_title">Your Library is Empty</string>
|
||||
<string name="empty_library_subtitle">Create new monster cards or import them from D&D Beyond or Open5e.</string>
|
||||
<string name="app_title_splash">Monster Cards</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<resources>
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
@@ -13,4 +13,9 @@
|
||||
<item name="android:windowBackground">@color/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
<!-- Instant starting theme displaying logo on launch -->
|
||||
<style name="Theme.App.Starting" parent="AppTheme">
|
||||
<item name="android:windowBackground">@color/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||