diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7765c6c..885890b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -31,7 +31,12 @@ android:theme="@style/AppTheme.NoActionBar"> + + @@ -50,12 +55,21 @@ android:launchMode="singleTask" android:theme="@style/AppTheme.NoActionBar"> + + + + + + + + diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/CreateGameActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/CreateGameActivity.java new file mode 100644 index 0000000..d19b52f --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/CreateGameActivity.java @@ -0,0 +1,691 @@ +package org.secuso.privacyfriendlysudoku.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.graphics.Point; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import com.google.android.material.navigation.NavigationView; + +import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.RatingBar; +import android.widget.TextView; +import android.widget.Toast; + +import org.secuso.privacyfriendlysudoku.controller.GameController; +import org.secuso.privacyfriendlysudoku.controller.GameStateManager; +import org.secuso.privacyfriendlysudoku.controller.SaveLoadStatistics; +import org.secuso.privacyfriendlysudoku.controller.Symbol; +import org.secuso.privacyfriendlysudoku.controller.helper.GameInfoContainer; +import org.secuso.privacyfriendlysudoku.controller.qqwing.QQWing; +import org.secuso.privacyfriendlysudoku.game.GameDifficulty; +import org.secuso.privacyfriendlysudoku.game.GameType; +import org.secuso.privacyfriendlysudoku.game.listener.IGameSolvedListener; +import org.secuso.privacyfriendlysudoku.game.listener.ITimerListener; +import org.secuso.privacyfriendlysudoku.ui.AboutActivity; +import org.secuso.privacyfriendlysudoku.ui.BaseActivity; +import org.secuso.privacyfriendlysudoku.ui.HelpActivity; +import org.secuso.privacyfriendlysudoku.ui.MainActivity; +import org.secuso.privacyfriendlysudoku.ui.SettingsActivity; +import org.secuso.privacyfriendlysudoku.ui.StatsActivity; +import org.secuso.privacyfriendlysudoku.ui.listener.IHintDialogFragmentListener; +import org.secuso.privacyfriendlysudoku.ui.listener.IResetDialogFragmentListener; +import org.secuso.privacyfriendlysudoku.ui.listener.IShareDialogFragmentListener; +import org.secuso.privacyfriendlysudoku.ui.view.CreateSudokuSpecialButtonLayout; +import org.secuso.privacyfriendlysudoku.ui.view.R; +import org.secuso.privacyfriendlysudoku.ui.view.SudokuFieldLayout; +import org.secuso.privacyfriendlysudoku.ui.view.SudokuKeyboardLayout; +import org.secuso.privacyfriendlysudoku.ui.view.SudokuSpecialButtonLayout; +import org.secuso.privacyfriendlysudoku.ui.view.WinDialog; +import org.secuso.privacyfriendlysudoku.ui.view.databinding.DialogFragmentShareBoardBinding; + + +import java.util.LinkedList; +import java.util.List; + +public class CreateGameActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, IGameSolvedListener ,ITimerListener, IHintDialogFragmentListener, IResetDialogFragmentListener, IShareDialogFragmentListener { + + GameController gameController; + SudokuFieldLayout layout; + SudokuKeyboardLayout keyboard; + SudokuSpecialButtonLayout specialButtonLayout; + TextView viewName ; + RatingBar ratingBar; + private boolean gameSolved = false; + private boolean startGame = true; + SaveLoadStatistics statistics = new SaveLoadStatistics(this); + WinDialog dialog = null; + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + if(gameSolved) { + gameController.pauseTimer(); + } else { + // start the game + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + gameController.startTimer(); + } + }, MAIN_CONTENT_FADEIN_DURATION); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + + if (sharedPref.getBoolean("pref_dark_mode_setting", false )) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + } + + if(sharedPref.getBoolean("pref_keep_screen_on", true)) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + GameType gameType = GameType.Unspecified; + GameDifficulty gameDifficulty = GameDifficulty.Unspecified; + int loadLevelID = 0; + boolean loadLevel = false; + + if(savedInstanceState == null) { + + Bundle extras = getIntent().getExtras(); + Uri data = getIntent().getData(); + gameController = new GameController(sharedPref, getApplicationContext()); + + boolean intentReceivedFromMainActivity = extras != null && + (extras.containsKey("gameType") || extras.containsKey("loadLevel")); + + if (data != null && !intentReceivedFromMainActivity) { + String input = ""; + if (data.getScheme().equals("sudoku")){ + input = data.getHost(); + } else if (data.getScheme().equals("http") && data.getHost().equals("sudoku")){ + input = data.getPath(); + input =input.replace("/", ""); + } + + int sectionSize = (int)Math.sqrt(input.length()); + int boardSize = sectionSize * sectionSize; + QQWing difficultyCheck; + GameInfoContainer container = new GameInfoContainer(0, GameDifficulty.Unspecified, + GameType.Unspecified, new int [boardSize], new int [boardSize], new boolean [boardSize][sectionSize]); + + try { + container.parseGameType("Default_" + sectionSize + "x" + sectionSize); + container.parseFixedValues(input); + + difficultyCheck = new QQWing(container.getGameType(), GameDifficulty.Unspecified); + difficultyCheck.setRecordHistory(true); + difficultyCheck.setPuzzle(container.getFixedValues()); + startGame = difficultyCheck.solve(); + container.parseDifficulty(difficultyCheck.getDifficulty().toString()); + + } catch (IllegalArgumentException e) { + startGame = false; + sectionSize = GameType.Default_9x9.getSize(); + boardSize = sectionSize * sectionSize; + container = new GameInfoContainer(0, GameDifficulty.Unspecified, + GameType.Default_9x9, new int [boardSize], new int [boardSize], new boolean [boardSize][sectionSize]); + } + + if (!startGame) { + AlertDialog.Builder builder = new AlertDialog.Builder(org.secuso.privacyfriendlysudoku.ui.CreateGameActivity.this, R.style.AppTheme_Dialog); + builder.setMessage(R.string.impossible_import_notice) + .setCancelable(false) + .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + finish(); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + } + + gameController.loadLevel(container); + + } else { + boolean isDailySudoku = false; + if (extras != null) { + gameType = GameType.valueOf(extras.getString("gameType", GameType.Default_9x9.name())); + gameDifficulty = GameDifficulty.valueOf(extras.getString("gameDifficulty", GameDifficulty.Moderate.name())); + isDailySudoku = extras.getBoolean("isDailySudoku", false); + loadLevel = extras.getBoolean("loadLevel", false); + if (loadLevel) { + loadLevelID = extras.getInt("loadLevelID"); + } + } + if (isDailySudoku) { + gameController.loadNewDailySudokuLevel(); + } else { + + List loadableGames = GameStateManager.getLoadableGameList(); + + if (loadLevel) { + if (loadableGames.size() > loadLevelID) { + // load level from GameStateManager + gameController.loadLevel(loadableGames.get(loadLevelID)); + } else if (loadLevelID == GameController.DAILY_SUDOKU_ID) { + for (GameInfoContainer container : loadableGames) { + if (container.getID() == loadLevelID) { + gameController.loadLevel(container); + break; + } + } + } + } else { + // load a new level + gameController.loadNewLevel(gameType, gameDifficulty); + } + } + } + } else { + gameController = savedInstanceState.getParcelable("gameController"); + // in case we get the same object back + // because parceling the Object does not always parcel it. Only if needed. + if(gameController != null) { + gameController.removeAllListeners(); + gameController.setContextAndSettings(getApplicationContext(), sharedPref); + } else { + // Error: no game could be restored. Go back to main menu. + Intent intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + finish(); + overridePendingTransition(0, 0); + } + gameSolved = savedInstanceState.getInt("gameSolved") == 1; + } + + + setContentView(R.layout.activity_create_sudoku); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + //toolbar.addView(); + + if(gameSolved) { + disableReset(); + } + + //Create new GameField + layout = (SudokuFieldLayout)findViewById(R.id.sudokuLayout); + gameController.registerGameSolvedListener(this); + gameController.registerTimerListener(this); + statistics.setGameController(gameController); + + layout.setSettingsAndGame(sharedPref, gameController); + + //set KeyBoard + keyboard = (SudokuKeyboardLayout) findViewById(R.id.sudokuKeyboardLayout); + keyboard.removeAllViews(); + keyboard.setGameController(gameController); + //keyboard.setColumnCount((gameController.getSize() / 2) + 1); + //keyboard.setRowCount(2); + Point p = new Point(); + getWindowManager().getDefaultDisplay().getSize(p); + + // set keyboard orientation + int orientation = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? + LinearLayout.HORIZONTAL : LinearLayout.VERTICAL; + + keyboard.setKeyBoard(gameController.getSize(), p.x,layout.getHeight()-p.y, orientation); + + + //set Special keys + CreateSudokuSpecialButtonLayout createSudokuSpecialButtonLayout = (CreateSudokuSpecialButtonLayout) findViewById(R.id.createSudokuLayout); + createSudokuSpecialButtonLayout.setButtons(p.x, gameController, keyboard, getFragmentManager(), orientation, org.secuso.privacyfriendlysudoku.ui.CreateGameActivity.this); + + + //set GameName + viewName = (TextView) findViewById(R.id.gameModeText); + viewName.setText(getString(gameController.getGameType().getStringResID())); + + //set Rating bar + List difficutyList = GameDifficulty.getValidDifficultyList(); + int numberOfStarts = difficutyList.size(); + ratingBar = (RatingBar) findViewById(R.id.gameModeStar); + + + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + drawer.setDrawerListener(toggle); + toggle.syncState(); + + NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + if(gameSolved) { + layout.setEnabled(false); + keyboard.setButtonsEnabled(false); + specialButtonLayout.setButtonsEnabled(false); + } + + gameController.notifyHighlightChangedListeners(); + gameController.notifyTimerListener(gameController.getTime()); + + // run this so the error list gets build again. + gameController.onModelChange(null); + + overridePendingTransition(0, 0); + } + + @Override + public void onPause(){ + super.onPause(); + if(!gameSolved && startGame) { + gameController.saveGame(this); + } + gameController.deleteTimer(); + } + + @Override + public void onNewIntent(Intent intent) { + super.onNewIntent(intent); + startActivity(intent); + finish(); + } + + @Override + public void onResume(){ + super.onResume(); + + View mainContent = findViewById(R.id.main_content); + if (mainContent != null) { + mainContent.animate().alpha(1).setDuration(MAIN_CONTENT_FADEOUT_DURATION); + } + + gameController.initTimer(); + + if(!gameSolved) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + gameController.startTimer(); + } + }, MAIN_CONTENT_FADEIN_DURATION); + } + + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + Symbol s; + try { + s = Symbol.valueOf(sharedPref.getString("pref_symbols", Symbol.Default.name())); + } catch(IllegalArgumentException e) { + s = Symbol.Default; + } + layout.setSymbols(s); + keyboard.setSymbols(s); + } + + + @Override + public void onBackPressed() { + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else { + finish(); + super.onBackPressed(); + } + } + + /*@Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.game_view, menu); + return true; + }*/ + + @SuppressWarnings("StatementWithEmptyBody") + @Override + public boolean onNavigationItemSelected(MenuItem item) { + // Handle navigation view item clicks here. + int id = item.getItemId(); + + Intent intent = null; + + switch(id) { + case R.id.menu_reset: + org.secuso.privacyfriendlysudoku.ui.GameActivity.ResetConfirmationDialog resetDialog = new org.secuso.privacyfriendlysudoku.ui.GameActivity.ResetConfirmationDialog(); + resetDialog.show(getFragmentManager(), "ResetDialogFragment"); + break; + + case R.id.menu_share: + String codeForClipboard = "sudoku://" + gameController.getCodeOfField(); + String codeForClipboard1 = "http://sudoku" + gameController.getCodeOfField(); + org.secuso.privacyfriendlysudoku.ui.GameActivity.ShareBoardDialog shareDialog = new org.secuso.privacyfriendlysudoku.ui.GameActivity.ShareBoardDialog(); + shareDialog.setDisplayCode(codeForClipboard); + shareDialog.setCopyClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // remember to include alternate code for older android versions + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + + if (clipboard != null) { + ClipData clip = ClipData.newPlainText("BoardCode", codeForClipboard); + clipboard.setPrimaryClip(clip); + Toast.makeText(org.secuso.privacyfriendlysudoku.ui.CreateGameActivity.this, R.string.copy_code_confirmation_toast, + Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(org.secuso.privacyfriendlysudoku.ui.CreateGameActivity.this, R.string.copy_code_error_toast, + Toast.LENGTH_LONG).show(); + } + } + }); + shareDialog.show(getFragmentManager(), "ShareDialogFragment"); + + break; + + case R.id.nav_newgame: + //create new game + intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + finish(); + break; + + case R.id.menu_settings: + //open settings + intent = new Intent(this, SettingsActivity.class); + intent.putExtra( PreferenceActivity.EXTRA_SHOW_FRAGMENT, SettingsActivity.GamePreferenceFragment.class.getName() ); + intent.putExtra( PreferenceActivity.EXTRA_NO_HEADERS, true ); + break; + + case R.id.nav_highscore: + // see highscore list + intent = new Intent(this, StatsActivity.class); + break; + + case R.id.menu_about: + //open about page + intent = new Intent(this, AboutActivity.class); + break; + + case R.id.menu_help: + //open about page + intent = new Intent(this, HelpActivity.class); + break; + default: + } + + if(intent != null) { + + final Intent i = intent; + // fade out the active activity + View mainContent = findViewById(R.id.main_content); + if (mainContent != null) { + mainContent.animate().alpha(0).setDuration(MAIN_CONTENT_FADEOUT_DURATION); + } + + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + startActivity(i); + overridePendingTransition(0, 0); + } + }, NAVDRAWER_LAUNCH_DELAY); + + } + + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } + + + @Override + public void onSolved() { + gameSolved = true; + + gameController.pauseTimer(); + gameController.deleteGame(this); + disableReset(); + + //Save solved sudoku, if it happens to be a daily sudoku, to daily sudoku database + if(gameController.getGameID() == GameController.DAILY_SUDOKU_ID) { + gameController.saveDailySudoku(org.secuso.privacyfriendlysudoku.ui.CreateGameActivity.this); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putBoolean("finishedForToday", true); + editor.apply(); + } + + //Show time hints new plus old best time + + statistics.saveGameStats(); + + boolean isNewBestTime = gameController.getUsedHints() == 0 + && statistics.loadStats(gameController.getGameType(),gameController.getDifficulty()).getMinTime() >= gameController.getTime(); + + dialog = new WinDialog(this, R.style.WinDialog , timeToString(gameController.getTime()), String.valueOf(gameController.getUsedHints()), isNewBestTime); + + dialog.getWindow().setContentView(R.layout.win_screen_layout); + //dialog.setContentView(getLayoutInflater().inflate(R.layout.win_screen_layout,null)); + //dialog.setContentView(R.layout.win_screen_layout); + dialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL); + dialog.getWindow().setBackgroundDrawableResource(R.color.transparent); + + //((TextView)dialog.findViewById(R.id.win_hints)).setText(gameController.getUsedHints()); + //((TextView)dialog.findViewById(R.id.win_time)).setText(timeToString(gameController.getTime())); + + dialog.show(); + + final Activity activity = this; + ((Button)dialog.findViewById(R.id.win_continue_button)).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + Intent intent = new Intent(activity, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + overridePendingTransition(0, 0); + activity.finish(); + } + }); + ((Button)dialog.findViewById(R.id.win_showGame_button)).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + + layout.setEnabled(false); + keyboard.setButtonsEnabled(false); + specialButtonLayout.setButtonsEnabled(false); + } + + public static String timeToString(int time) { + int seconds = time % 60; + int minutes = ((time - seconds) / 60) % 60; + int hours = (time - minutes - seconds) / (3600); + String h, m, s; + s = (seconds < 10) ? "0" + String.valueOf(seconds) : String.valueOf(seconds); + m = (minutes < 10) ? "0" + String.valueOf(minutes) : String.valueOf(minutes); + h = (hours < 10) ? "0" + String.valueOf(hours) : String.valueOf(hours); + return h + ":" + m + ":" + s; + } + + + private void disableReset(){ + NavigationView navView = (NavigationView)findViewById(R.id.nav_view); + Menu navMenu = navView.getMenu(); + navMenu.findItem(R.id.menu_reset).setEnabled(false); + } + @Override + public void onTick(int time) { + + // display the time + + if(gameSolved || !startGame) return; + // save time + gameController.saveGame(this); + } + + @Override + public void onHintDialogPositiveClick() { + gameController.hint(); + } + + @Override + public void onResetDialogPositiveClick() { + gameController.resetLevel(); + } + + @Override + public void onShareDialogPositiveClick(String input) { + Intent sendBoardIntent = new Intent(); + sendBoardIntent.setAction(Intent.ACTION_SEND); + sendBoardIntent.putExtra(Intent.EXTRA_TEXT, input); + sendBoardIntent.setType("text/plain"); + + Intent shareBoardIntent = Intent.createChooser(sendBoardIntent, null); + startActivity(shareBoardIntent); + } + + @Override + public void onDialogNegativeClick() { + // do nothing + } + + public static class ShareBoardDialog extends DialogFragment { + private LinkedList listeners = new LinkedList<>(); + + /*declare empty display code and click listener in case anyone + * tries to call the ShareBoardDialog without setting those attributes first + */ + + private String displayCode = ""; + private View.OnClickListener copyClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }; + + public void setDisplayCode(String displayCode) { + this.displayCode = displayCode; + } + + public void setCopyClickListener(View.OnClickListener listener) { + copyClickListener = listener; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + // Verify that the host activity implements the callback interface + if(activity instanceof IShareDialogFragmentListener) { + listeners.add((IShareDialogFragmentListener) activity); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_Dialog); + + LayoutInflater inflater = getActivity().getLayoutInflater(); + DialogFragmentShareBoardBinding binding = DialogFragmentShareBoardBinding.inflate(inflater); + + binding.ver3DisplaySudokuTextView.setText(displayCode); + binding.ver3CopySudokuToClipboardButton.setOnClickListener(copyClickListener); + builder.setView(binding.getRoot()); + + builder.setPositiveButton(R.string.share_confirmation_confirm, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + for(IShareDialogFragmentListener l : listeners) { + l.onShareDialogPositiveClick(binding.ver3DisplaySudokuTextView.getText().toString()); + } + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + return builder.create(); + } + } + + public static class ResetConfirmationDialog extends DialogFragment { + + LinkedList listeners = new LinkedList<>(); + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + // Verify that the host activity implements the callback interface + if(activity instanceof IResetDialogFragmentListener) { + listeners.add((IResetDialogFragmentListener) activity); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // Use the Builder class for convenient dialog construction + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_Dialog); + builder.setMessage(R.string.reset_confirmation) + .setPositiveButton(R.string.reset_confirmation_confirm, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + for(IResetDialogFragmentListener l : listeners) { + l.onResetDialogPositiveClick(); + } + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + return builder.create(); + } + } + + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + // Save the user's current game state + + savedInstanceState.putParcelable("gameController", gameController); + savedInstanceState.putInt("gameSolved", gameSolved ? 1 : 0); + + // Always call the superclass so it can save the view hierarchy state + super.onSaveInstanceState(savedInstanceState); + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) { + //super.onRestoreInstanceState(savedInstanceState); + } + +} diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/DailySudokuActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/DailySudokuActivity.java similarity index 96% rename from app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/DailySudokuActivity.java rename to app/src/main/java/org/secuso/privacyfriendlysudoku/ui/DailySudokuActivity.java index d8800a1..43aa30a 100644 --- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/DailySudokuActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/DailySudokuActivity.java @@ -1,4 +1,4 @@ -package org.secuso.privacyfriendlysudoku.ui.view; +package org.secuso.privacyfriendlysudoku.ui; import android.content.Context; import android.content.Intent; @@ -18,20 +18,17 @@ import android.view.View; import android.widget.RatingBar; import android.widget.Toast; import org.secuso.privacyfriendlysudoku.controller.GameController; -import org.secuso.privacyfriendlysudoku.controller.GameStateManager; import org.secuso.privacyfriendlysudoku.controller.NewLevelManager; import org.secuso.privacyfriendlysudoku.controller.database.DatabaseHelper; import org.secuso.privacyfriendlysudoku.controller.database.model.DailySudoku; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import org.secuso.privacyfriendlysudoku.controller.SaveLoadStatistics; -import org.secuso.privacyfriendlysudoku.controller.helper.GameInfoContainer; import org.secuso.privacyfriendlysudoku.controller.qqwing.QQWing; import org.secuso.privacyfriendlysudoku.game.GameDifficulty; import org.secuso.privacyfriendlysudoku.game.GameType; -import org.secuso.privacyfriendlysudoku.ui.GameActivity; -import org.secuso.privacyfriendlysudoku.ui.SettingsActivity; -import org.secuso.privacyfriendlysudoku.ui.StatsActivity; +import org.secuso.privacyfriendlysudoku.ui.view.R; + import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/GameActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/GameActivity.java index 4e5982c..6a504e8 100644 --- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/GameActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/GameActivity.java @@ -17,6 +17,8 @@ import android.os.Bundle; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import com.google.android.material.navigation.NavigationView; + +import androidx.appcompat.app.AppCompatDelegate; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.appcompat.app.ActionBarDrawerToggle; @@ -96,6 +98,12 @@ public class GameActivity extends BaseActivity implements NavigationView.OnNavig SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + if (sharedPref.getBoolean("pref_dark_mode_setting", false )) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + } + if(sharedPref.getBoolean("pref_keep_screen_on", true)) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } @@ -115,8 +123,13 @@ public class GameActivity extends BaseActivity implements NavigationView.OnNavig (extras.containsKey("gameType") || extras.containsKey("loadLevel")); if (data != null && !intentReceivedFromMainActivity) { - String input = data.toString(); - input = input.replace("sudoku://", ""); + String input = ""; + if (data.getScheme().equals("sudoku")){ + input = data.getHost(); + } else if (data.getScheme().equals("http") && data.getHost().equals("sudoku")){ + input = data.getPath(); + input =input.replace("/", ""); + } int sectionSize = (int)Math.sqrt(input.length()); int boardSize = sectionSize * sectionSize; @@ -372,6 +385,7 @@ public class GameActivity extends BaseActivity implements NavigationView.OnNavig case R.id.menu_share: String codeForClipboard = "sudoku://" + gameController.getCodeOfField(); + String codeForClipboard1 = "http://sudoku" + gameController.getCodeOfField(); ShareBoardDialog shareDialog = new ShareBoardDialog(); shareDialog.setDisplayCode(codeForClipboard); shareDialog.setCopyClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java index 4a378c4..7973ad6 100644 --- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java @@ -2,10 +2,13 @@ package org.secuso.privacyfriendlysudoku.ui; import android.content.Intent; import android.content.SharedPreferences; +import android.media.audiofx.Equalizer; import android.os.Bundle; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import com.google.android.material.navigation.NavigationView; + +import androidx.appcompat.app.AppCompatDelegate; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; @@ -13,7 +16,6 @@ import androidx.core.view.GravityCompat; import androidx.viewpager.widget.ViewPager; import androidx.drawerlayout.widget.DrawerLayout; import androidx.appcompat.app.ActionBarDrawerToggle; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import android.view.LayoutInflater; import android.view.MenuItem; @@ -30,7 +32,6 @@ import org.secuso.privacyfriendlysudoku.controller.NewLevelManager; import org.secuso.privacyfriendlysudoku.controller.helper.GameInfoContainer; import org.secuso.privacyfriendlysudoku.game.GameDifficulty; import org.secuso.privacyfriendlysudoku.game.GameType; -import org.secuso.privacyfriendlysudoku.ui.view.DailySudokuActivity; import org.secuso.privacyfriendlysudoku.ui.view.R; import java.util.LinkedList; @@ -56,8 +57,22 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + settings = PreferenceManager.getDefaultSharedPreferences(this); + if (settings.getBoolean("pref_dark_mode_setting", false )) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); + + } else if (settings.getBoolean("pref_dark_mode_automatically_by_system", false)) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); + + } else if(settings.getBoolean("pref_dark_mode_automatically_by_battery", false)){ + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY); + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + } + NewLevelManager newLevelManager = NewLevelManager.getInstance(getApplicationContext(), settings); // check if we need to pre generate levels. diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/SettingsActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/SettingsActivity.java index 448b560..f6c20fd 100644 --- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/SettingsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/SettingsActivity.java @@ -3,6 +3,8 @@ package org.secuso.privacyfriendlysudoku.ui; import android.annotation.TargetApi; import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; @@ -10,14 +12,19 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatDelegate; + import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.view.MenuItem; import android.view.View; +import android.widget.CompoundButton; +import android.widget.Switch; import org.secuso.privacyfriendlysudoku.ui.view.R; import java.util.List; +import java.util.Map; /** * A {@link PreferenceActivity} that presents a set of application settings. On @@ -43,12 +50,51 @@ public class SettingsActivity extends AppCompatPreferenceActivity { mainContent.setAlpha(0); mainContent.animate().alpha(1).setDuration(BaseActivity.MAIN_CONTENT_FADEIN_DURATION); } + /** + * Set up the {@link android.app.ActionBar}, if the API is available. + */ + + SharedPreferences preferenceManager = PreferenceManager + .getDefaultSharedPreferences(this); + + SharedPreferences.OnSharedPreferenceChangeListener x = new SharedPreferences.OnSharedPreferenceChangeListener() { + + + public void recheckNightModeProperties(SharedPreferences sharedPreferences){ + if (sharedPreferences.getBoolean("pref_dark_mode_setting", false )) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); + restartActivity(); + + } else if (sharedPreferences.getBoolean("pref_dark_mode_automatically_by_system", false)) { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); + restartActivity(); + } else if(sharedPreferences.getBoolean("pref_dark_mode_automatically_by_battery", false)){ + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY); + restartActivity(); + } else { + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + restartActivity(); + } + + } + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals("pref_dark_mode_setting")|| key.equals("pref_dark_mode_automatically_by_system")||key.equals("pref_dark_mode_automatically_by_battery")) { + recheckNightModeProperties(sharedPreferences); + } + } + }; + preferenceManager.registerOnSharedPreferenceChangeListener(x); + } - /** - * Set up the {@link android.app.ActionBar}, if the API is available. - */ - private void setupActionBar() { + public void restartActivity() { + Intent i = new Intent(getApplicationContext(), MainActivity.class); + finish(); + startActivity(i); + } + + private void setupActionBar () { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { // Show the Up button in the action bar. @@ -69,7 +115,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity { return super.onMenuItemSelected(featureId, item); } - /** * {@inheritDoc} */ diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuButtonType.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuButtonType.java new file mode 100644 index 0000000..ab4c276 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuButtonType.java @@ -0,0 +1,56 @@ +package org.secuso.privacyfriendlysudoku.ui.view; + +import androidx.annotation.DrawableRes; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Chris on 15.11.2015. + */ +public enum CreateSudokuButtonType { + Unspecified(R.drawable.ic_accessibility_black_48dp),// placeholder + Value(R.drawable.ic_accessibility_black_48dp), // should be non picture + Do(R.drawable.ic_redo_black_48dp), + Undo(R.drawable.ic_undo_black_48dp), + NoteToggle(R.drawable.ic_create_black_48dp), + Spacer(R.drawable.ic_accessibility_black_48dp),//placeholder + Delete(R.drawable.ic_delete_black_48dp), + Finalize(R.drawable.ic_finalize), + Reset(R.drawable.ic_settings_backup_restore_black_48dp); + + + private int resID; + + CreateSudokuButtonType(@DrawableRes int res){ + this.resID = res; + } + + public int getResID() { + return resID; + } + + public static List getSpecialButtons() { + ArrayList result = new ArrayList(); + result.add(Undo); + result.add(Do); + result.add(Finalize); + //result.add(Spacer); + result.add(Delete); + result.add(NoteToggle); + return result; + } + public static String getName(CreateSudokuButtonType type) { + switch (type) { + case Do: return "Do"; + case Undo: return "Un"; + case Finalize: return "Fi"; + case NoteToggle: return "On"; + case Spacer: return ""; + case Delete: return "Del"; + default:return "NotSet"; + } + } +} + + diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuSpecialButton.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuSpecialButton.java new file mode 100644 index 0000000..6d93e6e --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuSpecialButton.java @@ -0,0 +1,23 @@ +package org.secuso.privacyfriendlysudoku.ui.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ImageButton; + +/** + * Created by TMZ_LToP on 07.12.2015. + */ +public class CreateSudokuSpecialButton extends ImageButton { + private int value = -1; + private CreateSudokuButtonType type = CreateSudokuButtonType.Unspecified; + + public CreateSudokuSpecialButton(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setValue(int value) { this.value = value; } + public void setType(CreateSudokuButtonType type) { this.type = type; } + public int getValue () { return value; } + public CreateSudokuButtonType getType() { return type; } + +} diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuSpecialButtonLayout.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuSpecialButtonLayout.java new file mode 100644 index 0000000..3fe8168 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/CreateSudokuSpecialButtonLayout.java @@ -0,0 +1,224 @@ +package org.secuso.privacyfriendlysudoku.ui.view; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.FragmentManager; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Toast; + +import androidx.core.content.ContextCompat; + +import org.secuso.privacyfriendlysudoku.controller.GameController; +import org.secuso.privacyfriendlysudoku.game.listener.IHighlightChangedListener; +import org.secuso.privacyfriendlysudoku.ui.GameActivity; +import org.secuso.privacyfriendlysudoku.ui.listener.IHintDialogFragmentListener; + +import java.util.LinkedList; + +import static org.secuso.privacyfriendlysudoku.ui.view.CreateSudokuButtonType.Spacer; +import static org.secuso.privacyfriendlysudoku.ui.view.CreateSudokuButtonType.getSpecialButtons; + +/** + * Created by TMZ_LToP on 17.11.2015. + */ +public class CreateSudokuSpecialButtonLayout extends LinearLayout implements IHighlightChangedListener { + + + CreateSudokuSpecialButton[] fixedButtons; + public int fixedButtonsCount = getSpecialButtons().size(); + GameController gameController; + SudokuKeyboardLayout keyboard; + Bitmap bitMap,bitResult; + Canvas canvas; + FragmentManager fragmentManager; + Context context; + + OnClickListener listener = new OnClickListener() { + @Override + public void onClick(View v) { + if(v instanceof CreateSudokuSpecialButton) { + CreateSudokuSpecialButton btn = (CreateSudokuSpecialButton)v; + + //int row = gameController.getSelectedRow(); + //int col = gameController.getSelectedCol(); + + switch(btn.getType()) { + case Delete: + gameController.deleteSelectedCellsValue(); + break; + case NoteToggle: + // rotates the Drawable + gameController.setNoteStatus(!gameController.getNoteStatus()); + keyboard.updateNotesEnabled(); + onHighlightChanged(); + break; + case Do: + gameController.ReDo(); + break; + case Undo: + gameController.UnDo(); + break; + case Finalize: + default: + break; + } + } + } + }; + + + public CreateSudokuSpecialButtonLayout(Context context, AttributeSet attrs) { + super(context, attrs); + setWeightSum(fixedButtonsCount); + this.context = context; + } + + public void setButtonsEnabled(boolean enabled) { + for(CreateSudokuSpecialButton b : fixedButtons) { + b.setEnabled(enabled); + } + } + + public void setButtons(int width, GameController gc, SudokuKeyboardLayout key, FragmentManager fm, int orientation, Context cxt) { + fragmentManager = fm; + keyboard=key; + gameController = gc; + context = cxt; + if(gameController != null) { + gameController.registerHighlightChangedListener(this); + } + fixedButtons = new CreateSudokuSpecialButton[fixedButtonsCount]; + LayoutParams p; + int i = 0; + //ArrayList type = (ArrayList) SudokuButtonType.getSpecialButtons(); + for (CreateSudokuButtonType t : getSpecialButtons()){ + fixedButtons[i] = new CreateSudokuSpecialButton(getContext(),null); + if(orientation == LinearLayout.HORIZONTAL) { + p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1); + } else { + p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1); + fixedButtons[i].setPadding(25, 0, 25, 0); + } + p.setMargins(5, 5, 5, 5); + + //int width2 =width/(fixedButtonsCount); + //p.width= width2-15; + if(t == Spacer) { + fixedButtons[i].setVisibility(View.INVISIBLE); + } + /*if(t == SudokuButtonType.Do && !gameController.isRedoAvailable()) { + fixedButtons[i].setEnabled(false); + } + if(t == SudokuButtonType.Undo && !gameController.isUndoAvailable()) { + fixedButtons[i].setEnabled(false); + }*/ + fixedButtons[i].setLayoutParams(p); + fixedButtons[i].setType(t); + fixedButtons[i].setImageDrawable(getResources().getDrawable(t.getResID())); + // fixedButtons[i].setText(SudokuButtonType.getName(t)); + fixedButtons[i].setScaleType(ImageView.ScaleType.CENTER); + fixedButtons[i].setAdjustViewBounds(true); + fixedButtons[i].setOnClickListener(listener); + fixedButtons[i].setBackgroundResource(R.drawable.numpad_highlighted_four); + addView(fixedButtons[i]); + + if(fixedButtons[i].getVisibility() == View.VISIBLE) { + Drawable drawable = ContextCompat.getDrawable(context, fixedButtons[i].getType().getResID()); + setUpVectorDrawable(drawable); + drawable.draw(canvas); + fixedButtons[i].setImageBitmap(bitResult); + } + i++; + } + + } + + @Override + public void onHighlightChanged() { + for(int i = 0; i < fixedButtons.length; i++) { + switch(fixedButtons[i].getType()) { + case Undo: + fixedButtons[i].setBackgroundResource(gameController.isUndoAvailable() ? + R.drawable.numpad_highlighted_four : R.drawable.inactive_button); + break; + case Do: + fixedButtons[i].setBackgroundResource(gameController.isRedoAvailable() ? + R.drawable.numpad_highlighted_four : R.drawable.inactive_button); + break; + case NoteToggle: + Drawable drawable = ContextCompat.getDrawable(context, fixedButtons[i].getType().getResID()); + setUpVectorDrawable(drawable); + + canvas.rotate(gameController.getNoteStatus() ? 45.0f : 0.0f, bitMap.getWidth()/2, bitMap.getHeight()/2); + canvas.drawBitmap(bitMap, 0, 0, null); + drawable.draw(canvas); + + fixedButtons[i].setImageBitmap(bitResult); + fixedButtons[i].setBackgroundResource(gameController.getNoteStatus() ? R.drawable.numpad_highlighted_three : R.drawable.numpad_highlighted_four); + + keyboard.updateNotesEnabled(); + + break; + default: + break; + } + } + } + + private void setUpVectorDrawable(Drawable drawable) { + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + bitMap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + bitResult = Bitmap.createBitmap(bitMap.getWidth(), bitMap.getHeight(), Bitmap.Config.ARGB_8888); + + canvas = new Canvas(bitResult); + } + /* + public static class HintConfirmationDialog extends DialogFragment { + + LinkedList listeners = new LinkedList<>(); + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + // Verify that the host activity implements the callback interface + if(activity instanceof IHintDialogFragmentListener) { + listeners.add((IHintDialogFragmentListener) activity); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // Use the Builder class for convenient dialog construction + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_Dialog); + builder.setMessage(R.string.hint_confirmation) + .setPositiveButton(R.string.hint_confirmation_confirm, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + for(IHintDialogFragmentListener l : listeners) { + l.onHintDialogPositiveClick(); + } + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + return builder.create(); + } + } + */ +} diff --git a/app/src/main/res/drawable/ic_finalize.xml b/app/src/main/res/drawable/ic_finalize.xml new file mode 100644 index 0000000..e57a943 --- /dev/null +++ b/app/src/main/res/drawable/ic_finalize.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_create_sudoku.xml b/app/src/main/res/layout/activity_create_sudoku.xml new file mode 100644 index 0000000..4763ba5 --- /dev/null +++ b/app/src/main/res/layout/activity_create_sudoku.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_game_view_create_sudoku.xml b/app/src/main/res/layout/content_game_view_create_sudoku.xml new file mode 100644 index 0000000..ff2d71c --- /dev/null +++ b/app/src/main/res/layout/content_game_view_create_sudoku.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/tutorial_slide1.xml b/app/src/main/res/layout/tutorial_slide1.xml index c24dd62..880eea7 100644 --- a/app/src/main/res/layout/tutorial_slide1.xml +++ b/app/src/main/res/layout/tutorial_slide1.xml @@ -2,7 +2,7 @@ + android:background="?attr/backgroundTutorialSlide"> + android:background="?attr/backgroundTutorialSlide"> + android:background="?attr/backgroundTutorialSlide"> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 1285f24..05fbbd2 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -10,6 +10,9 @@ Einstellungen + Nachtmodus + Nachtmodus + Wechsel zwischen Tages und Nacht Modus In Zusammenarbeit mit: diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index 5ca9ee4..81dbff3 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -20,6 +20,8 @@ @color/middlegrey @color/yellow @color/cardview_dark_background + @color/colorPrimaryDark + @color/colorPrimaryDark