diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/androidTest/java/com/x8192bit/diyeditmobile/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/x8192bit/diyeditmobile/ExampleInstrumentedTest.java new file mode 100644 index 0000000..d6ffa06 --- /dev/null +++ b/app/src/androidTest/java/com/x8192bit/diyeditmobile/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.x8192bit.diyeditmobile; + +import static org.junit.Assert.assertEquals; + +import android.content.Context; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.Test; +import org.junit.runner.RunWith; + + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.x8192Bit.DIYEdit_Mobile", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/AboutActivity.java b/app/src/main/java/com/x8192bit/diyeditmobile/AboutActivity.java new file mode 100644 index 0000000..dfe43fa --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/AboutActivity.java @@ -0,0 +1,49 @@ +package com.x8192bit.diyeditmobile; + +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; + +import androidx.appcompat.app.ActionBar; + +import x8192Bit.DIYEdit_Mobile.R; + +public class AboutActivity extends BaseActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.about_activity); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } + findViewById(R.id.about_about_btn).setOnClickListener(this::OnAboutButtonClicked); + findViewById(R.id.about_osl_btn).setOnClickListener(this::OnLicenseButtonClicked); + OnAboutButtonClicked(null); + TextView tv = findViewById(R.id.about_info_tv); + tv.setText(getString(R.string.aboutTextKey).replace("\\n", "\n")); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + this.finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void OnAboutButtonClicked(View v) { + ((TextView) findViewById(R.id.about_info_tv)).setText(getString(R.string.aboutTextKey).replace("\\n", "\n")); + } + + + private void OnLicenseButtonClicked(View v) { + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/BaseActivity.java b/app/src/main/java/com/x8192bit/diyeditmobile/BaseActivity.java index b2ab415..2f8ef07 100644 --- a/app/src/main/java/com/x8192bit/diyeditmobile/BaseActivity.java +++ b/app/src/main/java/com/x8192bit/diyeditmobile/BaseActivity.java @@ -1,7 +1,6 @@ package com.x8192bit.diyeditmobile; import android.content.Context; -import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; @@ -9,6 +8,8 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import com.x8192bit.diyeditmobile.utils.SPUtils; + import java.util.Locale; public class BaseActivity extends AppCompatActivity { @@ -20,17 +21,16 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { } public void changeLanguage(Context context) { - if (context == null) { - return; - } Resources resources = context.getResources(); Configuration configuration = resources.getConfiguration(); - SharedPreferences sp = context.getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); - String language = sp.getString("LanguageSelect", "system"); - if (!language.equals("system")) { - String[] str = language.split("-"); - configuration.locale = new Locale(str[0], str[1]); - } + configuration.locale = SPUtils.getLocale(context); + resources.updateConfiguration(configuration, null); + } + + public void changeLanguage(Context context, Locale locale) { + Resources resources = context.getResources(); + Configuration configuration = resources.getConfiguration(); + configuration.locale = locale; resources.updateConfiguration(configuration, null); } diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/FileSelectActivity.java b/app/src/main/java/com/x8192bit/diyeditmobile/FileSelectActivity.java new file mode 100644 index 0000000..46bed30 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/FileSelectActivity.java @@ -0,0 +1,230 @@ +package com.x8192bit.diyeditmobile; + +import static com.x8192bit.diyeditmobile.MainActivity.CHOOSE_RESULT; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.IS_IMPORT_MIO; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.IS_SAVE_EDIT; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.SAVE_EDIT_COUNT; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Environment; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; + +import com.x8192bit.diyeditmobile.utils.SPUtils; + +import java.io.File; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +import x8192Bit.DIYEdit_Mobile.R; + + +public class FileSelectActivity extends BaseActivity { + // TODO 快点重构你这坨狗屎 + public static final int CHOOSE_FILE = 0; + public static final int CHOOSE_DIRECTORY = 1; + File CurrentPath = null; + private int chooseType = CHOOSE_FILE; + private boolean isImportMIO; + private boolean isSaveEdit; + private int saveEditCount; + private boolean isTimeSorted; + private boolean isNormalOrder; + private boolean showHiddenFiles; + public AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + File originalPath = CurrentPath; + try { + String path = (String) (((TextView) ((LinearLayout) view).getChildAt(1))).getText(); + if (path.equals("..")) { + CurrentPath = CurrentPath.getParentFile(); + } else { + CurrentPath = new File(CurrentPath.getAbsolutePath() + '/' + path); + if (CurrentPath.isFile() && chooseType == CHOOSE_FILE) { + Intent intentResult = new Intent(); + intentResult.putExtra(CHOOSE_RESULT, CurrentPath.getAbsolutePath()); + intentResult.putExtra(IS_SAVE_EDIT, isSaveEdit); + if (isSaveEdit) { + intentResult.putExtra(IS_IMPORT_MIO, isImportMIO); + intentResult.putExtra(SAVE_EDIT_COUNT, saveEditCount); + } + setResult(1919810, intentResult); + finish(); + } + } + refreshList(getApplicationContext()); + } catch (NullPointerException e) { + CurrentPath = originalPath; + } catch (Exception e) { + new AlertDialog.Builder(FileSelectActivity.this) + .setTitle("What the fuck????!!") + .setMessage("GO FUCK YOURSELF!!!!!!!!!!!!!!!!!11").show(); + CurrentPath = originalPath; + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.fileselect_activity); + + Intent intent = getIntent(); + chooseType = intent.getIntExtra(MainActivity.CHOOSE_TYPE, CHOOSE_FILE); + + Button selectDirectoryButton = findViewById(R.id.file_select_ok_btn); + + if (chooseType == CHOOSE_FILE) { + // When selecting a file, the OK button is useless so remove + ((LinearLayout) findViewById(R.id.file_select_ll)).removeView(selectDirectoryButton); + } else { + selectDirectoryButton.setOnClickListener(v -> { + try { + Intent intentResult = new Intent(); + String path = CurrentPath.getAbsolutePath(); + intentResult.putExtra(CHOOSE_RESULT, path); + intentResult.putExtra(IS_SAVE_EDIT, isSaveEdit); + if (isSaveEdit) { + intentResult.putExtra(IS_IMPORT_MIO, isImportMIO); + intentResult.putExtra(SAVE_EDIT_COUNT, saveEditCount); + } + setResult(1919810, intentResult); + finish(); + } catch (Exception e) { + new AlertDialog.Builder(FileSelectActivity.this) + .setTitle("What the fuck????!!") + .setMessage("GO FUCK YOURSELF!!!!!!!!!!!!!!!!!11").show(); + } + }); + } + isSaveEdit = intent.getBooleanExtra(IS_SAVE_EDIT, false); + if (isSaveEdit) { + isImportMIO = intent.getBooleanExtra(IS_IMPORT_MIO, false); + saveEditCount = intent.getIntExtra(SAVE_EDIT_COUNT, 0); + } + + // initialize the actionbar so that we can add some button to it then + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + CurrentPath = Environment.getExternalStorageDirectory(); + + ListView fileChooser = findViewById(R.id.file_select_lv); + + isTimeSorted = SPUtils.isTimeSorted(getApplicationContext()); + isNormalOrder = SPUtils.isNormalOrder(getApplicationContext()); + showHiddenFiles = SPUtils.isShowingHiddenFiles(getApplicationContext()); + + refreshList(getApplicationContext()); + + fileChooser.setOnItemClickListener(listener); + } + + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + this.finish(); + return true; + } else { + if (item.getItemId() == 0) { + isTimeSorted = !isTimeSorted; + SPUtils.setTimeSorted(getApplicationContext(), isTimeSorted); + refreshList(getApplicationContext()); + } else if (item.getItemId() == 1) { + isNormalOrder = !isNormalOrder; + SPUtils.setNormalOrder(getApplicationContext(), isNormalOrder); + refreshList(getApplicationContext()); + } else if (item.getItemId() == 2) { + showHiddenFiles = !showHiddenFiles; + SPUtils.setShowingHiddenFiles(getApplicationContext(), showHiddenFiles); + refreshList(getApplicationContext()); + } + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.clear(); + menu.add(0, 0, 0, isTimeSorted ? R.string.nameSortedKey : R.string.timeSortedKey); + menu.add(0, 1, 1, isNormalOrder ? R.string.normalOrderKey : R.string.reverseOrderKey); + menu.add(0, 2, 2, showHiddenFiles ? R.string.hideHiddenFilesKey : R.string.showHiddenFilesKey); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + menu.clear(); + menu.add(0, 0, 0, isTimeSorted ? R.string.nameSortedKey : R.string.timeSortedKey); + menu.add(0, 1, 1, isNormalOrder ? R.string.normalOrderKey : R.string.reverseOrderKey); + menu.add(0, 2, 2, showHiddenFiles ? R.string.hideHiddenFilesKey : R.string.showHiddenFilesKey); + return super.onPrepareOptionsMenu(menu); + } + + public void refreshList(Context c) { + ListView fileChooser = findViewById(R.id.file_select_lv); + TextView PathView = findViewById(R.id.file_select_dir_tv); + String[] from = {"img", "text"}; + int[] to = {R.id.file_select_item_iv, R.id.file_select_item_tv}; + ArrayList> files = new ArrayList<>(); + + for (File f : Objects.requireNonNull(CurrentPath.listFiles())) { + if (showHiddenFiles || !f.isHidden()) { + HashMap file = new HashMap<>(); + if (f.isFile()) { + String[] split = f.getName().split("\\."); + if (f.getName().equals("MDATA") || f.getName().equals("GDATA") || f.getName().equals("RDATA")) { + file.put("img", R.drawable.save_wii); + } else if (split.length > 1 && (split[split.length - 1].equals("sav") || split[split.length - 1].equals("dsv"))) { + file.put("img", R.drawable.save_ds); + } else if (split.length > 1 && split[split.length - 1].equals("mio")) { + file.put("img", R.mipmap.ic_launcher_foreground); + } else { + file.put("img", R.drawable.baseline_file_open_24); + } + } else if (f.isDirectory()) { + file.put("img", R.drawable.directory); + } + file.put("text", f.getName()); + file.put("date", f.lastModified()); + files.add(file); + } + } + if (isTimeSorted) { + Collections.sort(files, (o1, o2) -> { + Comparator comparator = Collator.getInstance(Locale.getDefault()); + return isNormalOrder ? comparator.compare(o1.get("text"), o2.get("text")) : -comparator.compare(o1.get("text"), o2.get("text")); + }); + } else { + Collections.sort(files, (o1, o2) -> (isNormalOrder ? (long) o1.get("date") > (long) o2.get("date") ? 1 : -1 : (long) o1.get("date") > (long) o2.get("date") ? -1 : 1)); + } + HashMap parentFolder = new HashMap<>(); + parentFolder.put("img", R.drawable.exit); + parentFolder.put("text", ".."); + parentFolder.put("date", 0); + files.add(0, parentFolder); + fileChooser.setAdapter(new SimpleAdapter(c, files, R.layout.file_select_item, from, to)); + PathView.setText(CurrentPath.getAbsolutePath()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/MainActivity.java b/app/src/main/java/com/x8192bit/diyeditmobile/MainActivity.java new file mode 100644 index 0000000..e888c08 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/MainActivity.java @@ -0,0 +1,212 @@ +package com.x8192bit.diyeditmobile; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.provider.Settings; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.x8192bit.diyeditmobile.utils.FileUtils; +import com.x8192bit.diyeditmobile.utils.SPUtils; + +import x8192Bit.DIYEdit_Mobile.BuildConfig; +import x8192Bit.DIYEdit_Mobile.R; + +public class MainActivity extends BaseActivity { + + public static final String REAL_PATH = "com.x8192Bit.DIYEdit_Mobile.REAL_PATH"; + public static final String CHOOSE_TYPE = "com.x8192Bit.DIYEdit_Mobile.CHOOSE_TYPE"; + public static final String CHOOSE_RESULT = "com.x8192Bit.DIYEdit_Mobile.CHOOSE_RESULT"; + + public static void setUIMode(String UIMode) { + switch (UIMode) { + case "system": + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); + break; + case "day": + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + break; + case "night": + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); + break; + } + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + if (intent.getData() != null) { + Uri uri = intent.getData(); + openFile(FileUtils.getFileAbsolutePath(this, uri)); + } + } + + // Create Method + @SuppressLint("SetTextI18n") + @Override + protected void onCreate(Bundle savedInstanceState) { + try { + super.onCreate(savedInstanceState); + setContentView(R.layout.main_activity); + + // set UI mode + setUIMode(SPUtils.getTheme(getApplicationContext())); + + // open file if opening a mio/save file from other app + if (getIntent().getData() != null) { + Uri uri = getIntent().getData(); + openFile(FileUtils.getFileAbsolutePath(this, uri)); + } + + // set version label + ((TextView) findViewById(R.id.main_version_tv)).setText(getText(R.string.app_name) + + " " + BuildConfig.VERSION_NAME + + " " + BuildConfig.BUILD_TYPE.toUpperCase()); + + // set click event + findViewById(R.id.main_open_file_btn).setOnClickListener(this::selectFile); + findViewById(R.id.main_recent_file_btn).setOnClickListener(this::openRecentFile); + findViewById(R.id.main_settings_btn).setOnClickListener(this::openSettingsMenu); + findViewById(R.id.main_exit_btn).setOnClickListener(this::exit); + + } catch (Exception e) { + new AlertDialog.Builder(getApplicationContext()) + .setMessage(e.getMessage()) + .show(); + } + } + + @Deprecated + public void selectFile(View v) { + try { + if (Build.VERSION.SDK_INT < 30) { + if (!checkBefore30()) { + requestBefore30(); + } else { + // User granted file permission, Access your file + readFiles(); + } + } else { + check30AndAfter(); + } + } catch (Exception e) { + new AlertDialog.Builder(MainActivity.this) + .setMessage(e.getMessage()) + .show(); + } + } + + private boolean checkBefore30() { + return ContextCompat.checkSelfPermission(MainActivity.this, + Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + } + + private void requestBefore30() { + if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)) { + Toast.makeText(MainActivity.this, R.string.storagePermissionRequireKey, Toast.LENGTH_LONG).show(); + ActivityCompat.requestPermissions(MainActivity.this, + new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100); + } else { + ActivityCompat.requestPermissions(MainActivity.this, + new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 100) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + readFiles(); + } else { + // Allow permission for storage access! + Toast.makeText(MainActivity.this, R.string.tryAgainKey, Toast.LENGTH_LONG).show(); + } + } + } + + @RequiresApi(api = Build.VERSION_CODES.R) + @Deprecated + private void check30AndAfter() { + if (!Environment.isExternalStorageManager()) { + try { + Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); + intent.addCategory("android.intent.category.DEFAULT"); + intent.setData(Uri.parse(String.format("package:%s", getApplicationContext().getPackageName()))); + startActivityForResult(intent, 200); + } catch (Exception e) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); + startActivityForResult(intent, 200); + } + } else { + readFiles(); + } + } + + private void readFiles() { + Intent intent = new Intent(this, FileSelectActivity.class); + intent.putExtra(CHOOSE_TYPE, FileSelectActivity.CHOOSE_FILE); + // TODO 快点重构你这坨狗屎 + startActivityForResult(intent, 114514); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 114514 && resultCode == 1919810) { + if (data != null) { + openFile(data.getStringExtra(CHOOSE_RESULT)); + } else { + new AlertDialog.Builder(getApplicationContext()) + .setTitle("嘿嘿!!") + .setMessage("安卓崩喽!安卓崩喽!!!1111") + .show(); + } + } + } + + // LOOSEN COUPLING BUT LOW PERFORMANCE!!!!11 + public void openRecentFile(View view) { + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this); + String[] HistoryItems = SPUtils.getHistoryItems(getApplicationContext()); + String[] HistoryPaths = SPUtils.getHistoryPaths(getApplicationContext()); + if (HistoryPaths.length == 0) { + alertDialogBuilder.setTitle(R.string.warningKey).setMessage(R.string.noHistoryKey).show(); + } else { + alertDialogBuilder.setTitle(R.string.openRecentFileKey).setItems(HistoryItems, (dialog, which) -> openFile(HistoryPaths[which])).show(); + } + } + + public void openSettingsMenu(View view) { + Intent intent = new Intent(this, SettingsActivity.class); + startActivity(intent); + } + + public void exit(View view) { + this.finish(); + } + + // Common method for open a file + private void openFile(String realPath) { + Intent intent = new Intent(this, SaveEditActivity.class); + intent.putExtra(REAL_PATH, realPath); + startActivity(intent); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/SaveEditActivity.java b/app/src/main/java/com/x8192bit/diyeditmobile/SaveEditActivity.java new file mode 100644 index 0000000..11dd3fa --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/SaveEditActivity.java @@ -0,0 +1,408 @@ +package com.x8192bit.diyeditmobile; + +import static com.x8192bit.diyeditmobile.MainActivity.CHOOSE_RESULT; +import static com.x8192bit.diyeditmobile.MainActivity.CHOOSE_TYPE; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.IS_IMPORT_MIO; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.IS_SAVE_EDIT; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.SAVE_EDIT_COUNT; + +import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.fragment.app.Fragment; +import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.viewpager2.widget.ViewPager2; + +import com.google.android.material.tabs.TabLayout; +import com.google.android.material.tabs.TabLayoutMediator; +import com.x8192bit.diyeditmobile.fragments.BGViewFragment; +import com.x8192bit.diyeditmobile.fragments.MIDIFragment; +import com.x8192bit.diyeditmobile.fragments.MetadataFragment; +import com.x8192bit.diyeditmobile.fragments.SaveEditFragment; +import com.x8192bit.diyeditmobile.fragments.UnlockFragment; +import com.xperia64.diyedit.FileByteOperations; +import com.xperia64.diyedit.metadata.Metadata; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; + +import x8192Bit.DIYEdit_Mobile.R; + +public class SaveEditActivity extends BaseActivity { + + public static final String OPEN_FILE_CHOOSE_ACTIVITY = "com.x8192Bit.DIYEdit_Mobile.OPEN_FILE_CHOOSE_ACTIVITY"; + public static final String FILE_CHOOSE_ACTIVITY_RESULT = "com.x8192Bit.DIYEdit_Mobile.FILE_CHOOSE_ACTIVITY_RESULT"; + public static final String FILE_CHOOSE_REAL_PATH = "com.x8192Bit.DIYEdit_Mobile.FILE_CHOOSE_REAL_PATH"; + private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Objects.equals(intent.getAction(), OPEN_FILE_CHOOSE_ACTIVITY)) { + // TODO 快点重构你这坨狗屎 + Intent i = new Intent(SaveEditActivity.this, FileSelectActivity.class); + i.putExtra(CHOOSE_TYPE, FileSelectActivity.CHOOSE_FILE); + i.putExtra(IS_SAVE_EDIT, intent.getBooleanExtra(IS_SAVE_EDIT, false)); + if (intent.getBooleanExtra(IS_SAVE_EDIT, false)) { + if (!intent.getBooleanExtra(IS_IMPORT_MIO, false)) { + i.putExtra(CHOOSE_TYPE, FileSelectActivity.CHOOSE_DIRECTORY); + } + i.putExtra(IS_IMPORT_MIO, intent.getBooleanExtra(IS_IMPORT_MIO, false)); + i.putExtra(SAVE_EDIT_COUNT, intent.getIntExtra(SAVE_EDIT_COUNT, 0)); + } + startActivityForResult(i, 114514); + } + } + }; + byte[] file; + int savetype = 0; + TabLayout tabs = null; + ImageView SaveIcon = null; + ViewPager2 vp2 = null; + ArrayList titleList = new ArrayList<>(); + int mio_type = 0; + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + this.finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = getIntent(); + String path = intent.getStringExtra(MainActivity.REAL_PATH); + initEnable(path); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } + registerBroadcastReceiver(); + } + + public void initEnable(String filePath) { + if (filePath != null) { + try { + file = FileByteOperations.read(filePath); + int length = file.length; + ArrayList fl = new ArrayList<>(); + if (length == 33554432 || length == 33554554 || length == 33566720 || length == 16777216) { + performDSSaveDATA(fl, filePath); + } else { + if (file.length == 4719808) { + performGDATA(fl, filePath); + } else if (length == 591040) { + performRDATA(fl, filePath); + } else if (length == 1033408) { + performMDATA(fl, filePath); + } else if (file.length == 6438592) { + performWiiCompressedDATA(fl, filePath); + } + } + + // Only detect when the file is not a save file + if (savetype == 0) { + if (file.length == 65536) { + performGAME(fl, filePath); + } else if (file.length == 8192) { + performRECORD(fl, filePath); + } else if (file.length == 14336) { + performMANGA(fl, filePath); + } + } + if (savetype != 0 || mio_type != 0) { + updateFileHistory(filePath); + vp2.setAdapter(new FragmentStateAdapter(this) { + @NonNull + @Override + public Fragment createFragment(int position) { + return fl.get(position); + } + + @Override + public int getItemCount() { + return fl.size(); + } + }); + new TabLayoutMediator(tabs, vp2, (tab, position) -> tab.setText(titleList.get(position))).attach(); + + } else { + fileUnavailableAlert(); + } + } catch (Exception e) { + + } + } else { + fileUnavailableAlert(); + } + } + + @SuppressLint("SetTextI18n") + private void performGDATA(ArrayList fl, String filePath) { + savetype |= 1; + setMenuType(contentViewType.SAVE); + TextView saveView = findViewById(R.id.save_info_tv); + saveView.setText(getText(R.string.wiiSaveKey) + " (GDATA)"); + TabLayout.Tab t0 = tabs.newTab(); + titleList.add(getResources().getString(R.string.editGameKey)); + tabs.addTab(t0, 0); + fl.add(SaveEditFragment.newInstance(filePath, 0)); + } + + @SuppressLint("SetTextI18n") + private void performRDATA(ArrayList fl, String filePath) { + savetype |= 2; + setMenuType(contentViewType.SAVE); + TextView saveView = findViewById(R.id.save_info_tv); + saveView.setText(getText(R.string.wiiSaveKey) + " (RDATA)"); + TabLayout.Tab t0 = tabs.newTab(); + titleList.add(getResources().getString(R.string.editRecordKey)); + tabs.addTab(t0, 0); + fl.add(SaveEditFragment.newInstance(filePath, 1)); + } + + @SuppressLint("SetTextI18n") + private void performMDATA(ArrayList fl, String filePath) { + savetype |= 4; + setMenuType(contentViewType.SAVE); + TextView saveView = findViewById(R.id.save_info_tv); + saveView.setText(getText(R.string.wiiSaveKey) + " (MDATA)"); + TabLayout.Tab t0 = tabs.newTab(); + titleList.add(getResources().getString(R.string.editMangaKey)); + tabs.addTab(t0, 0); + fl.add(SaveEditFragment.newInstance(filePath, 2)); + } + + private void performWiiCompressedDATA(ArrayList fl, String filePath) { + savetype |= 7; + setMenuType(contentViewType.SAVE); + setContentView(R.layout.save_file_menu_activity); + tabs = findViewById(R.id.mio_tabs); + TabLayout.Tab t0 = tabs.newTab(); + TabLayout.Tab t1 = tabs.newTab(); + TabLayout.Tab t2 = tabs.newTab(); + titleList.add(getResources().getString(R.string.editGameKey)); + titleList.add(getResources().getString(R.string.editRecordKey)); + titleList.add(getResources().getString(R.string.editMangaKey)); + tabs.addTab(t0, 0); + tabs.addTab(t1, 1); + tabs.addTab(t2, 2); + fl.add(SaveEditFragment.newInstance(filePath, 0)); + fl.add(SaveEditFragment.newInstance(filePath, 1)); + fl.add(SaveEditFragment.newInstance(filePath, 2)); + } + + private void setMenuType(contentViewType tvv) { + if (tvv == contentViewType.MIO && mio_type != 0) { + setContentView(R.layout.mio_menu_activity); + vp2 = findViewById(R.id.mio_vp); + } + if (tvv == contentViewType.SAVE && savetype != 0) { + setContentView(R.layout.save_file_menu_activity); + vp2 = findViewById(R.id.save_vp); + } + if (tabs == null) { + tabs = findViewById(R.id.mio_tabs); + } + } + + private void performGAME(ArrayList fl, String filePath) { + mio_type = 3; + setMenuType(contentViewType.MIO); + TabLayout.Tab t0 = tabs.newTab(); + TabLayout.Tab t1 = tabs.newTab(); + TabLayout.Tab t2 = tabs.newTab(); + //TabLayout.Tab t3 = tabs.newTab(); + titleList.add(getResources().getString(R.string.metaDataEditKey)); + titleList.add(getResources().getString(R.string.viewBGKey)); + titleList.add(getResources().getString(R.string.midiToolsKey)); + //titleList.add(getResources().getString(R.string.exportAllOBJKey)); + tabs.addTab(t0, 0); + tabs.addTab(t1, 1); + tabs.addTab(t2, 2); + //tabs.addTab(t3, 3); + fl.add(MetadataFragment.newInstance(filePath, 0)); + fl.add(BGViewFragment.newInstance(filePath, true)); + fl.add(MIDIFragment.newInstance(filePath, true)); + setMioMetadataEntries(filePath); + } + + private void performMANGA(ArrayList fl, String filePath) { + mio_type = 2; + setMenuType(contentViewType.MIO); + TabLayout.Tab t0 = tabs.newTab(); + TabLayout.Tab t1 = tabs.newTab(); + titleList.add(getResources().getString(R.string.metaDataEditKey)); + titleList.add(getResources().getString(R.string.viewMangaKey)); + tabs.addTab(t0, 0); + tabs.addTab(t1, 1); + fl.add(MetadataFragment.newInstance(filePath, 2)); + fl.add(BGViewFragment.newInstance(filePath, false)); + setMioMetadataEntries(filePath); + } + + private void performDSSaveDATA(ArrayList fl, String filePath) { + savetype |= 8; + setMenuType(contentViewType.SAVE); + TextView saveView = findViewById(R.id.save_info_tv); + saveView.setText(R.string.dsSaveKey); + SaveIcon = findViewById(R.id.save_info_iv); + SaveIcon.setImageDrawable(AppCompatResources.getDrawable(this, R.drawable.save_ds)); + tabs = findViewById(R.id.mio_tabs); + TabLayout.Tab t0 = tabs.newTab(); + TabLayout.Tab t1 = tabs.newTab(); + TabLayout.Tab t2 = tabs.newTab(); + TabLayout.Tab t3 = tabs.newTab(); + titleList.add(getResources().getString(R.string.editGameKey)); + titleList.add(getResources().getString(R.string.editRecordKey)); + titleList.add(getResources().getString(R.string.editMangaKey)); + titleList.add(getResources().getString(R.string.unlockKey)); + tabs.addTab(t0, 0); + tabs.addTab(t1, 1); + tabs.addTab(t2, 2); + tabs.addTab(t3, 3); + fl.add(SaveEditFragment.newInstance(filePath, 0)); + fl.add(SaveEditFragment.newInstance(filePath, 1)); + fl.add(SaveEditFragment.newInstance(filePath, 2)); + fl.add(UnlockFragment.newInstance(filePath)); + } + + + private void updateFileHistory(String realPath) { + SharedPreferences sp = SaveEditActivity.this.getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); + try { + int historyCount = Integer.parseInt(sp.getString("maxHistoryCount", "10")); + SharedPreferences.Editor ed = sp.edit(); + String history = sp.getString("history", null); + StringBuilder sb = new StringBuilder(); + if (history != null) { + ArrayList historyArray = new ArrayList<>(Arrays.asList(history.split(","))); + boolean isDuplicated = false; + for (int i = 0; i < historyArray.size(); i++) { + if (historyArray.get(i).equals(realPath)) { + historyArray.remove(i); + break; + } + } + historyArray.add(0, realPath); + if (historyArray.size() > historyCount) { + do { + historyArray.remove(historyCount - 1); + } while (historyArray.size() == historyCount); + } + for (int i = 0; i < historyArray.size(); i++) { + sb.append(historyArray.get(i)).append(","); + } + } else { + sb.append(realPath); + } + ed.putString("history", sb.toString()); + ed.apply(); + } catch (NumberFormatException e) { + e.printStackTrace(); + Toast.makeText(getApplicationContext(), R.string.numberRequiredKey, Toast.LENGTH_SHORT).show(); + this.finish(); + } + } + + private void performRECORD(ArrayList fl, String filePath) { + mio_type = 1; + setMenuType(contentViewType.MIO); + TabLayout.Tab t0 = tabs.newTab(); + TabLayout.Tab t1 = tabs.newTab(); + titleList.add(getResources().getString(R.string.metaDataEditKey)); + titleList.add(getResources().getString(R.string.midiToolsKey)); + tabs.addTab(t0, 0); + tabs.addTab(t1, 1); + fl.add(MetadataFragment.newInstance(filePath, 1)); + fl.add(MIDIFragment.newInstance(filePath, false)); + setMioMetadataEntries(filePath); + } + + private void fileUnavailableAlert() { + new AlertDialog.Builder(SaveEditActivity.this) + .setTitle(R.string.warningKey) + .setMessage(R.string.couldNotReadFileKey) + .setCancelable(false) + .setNeutralButton(R.string.backKey, (dialog, which) -> SaveEditActivity.this.finish()) + .show(); + } + + @SuppressLint("DefaultLocale") + private void setMioMetadataEntries(String filePath) { + TextView MTimeLabel = findViewById(R.id.mio_info_date_value_tv); + TextView MAuthorLabel = findViewById(R.id.mio_info_author_value_tv); + TextView MCompanyLabel = findViewById(R.id.mio_info_company_value_tv); + TextView MNameLabel = findViewById(R.id.mio_info_name_value_tv); + Metadata m = new Metadata(filePath); + MCompanyLabel.setText(m.getBrand()); + MAuthorLabel.setText(m.getCreator()); + MNameLabel.setText(m.getName()); + DateTime date = new DateTime(2000, 1, 1, 0, 0, 0, 0); + date = date.plusDays(m.getTimestamp()); + MTimeLabel.setText(String.format("%04d-%02d-%02d", date.getYear(), date.getMonthOfYear(), date.getDayOfMonth())); + } + + public void registerBroadcastReceiver() { + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(OPEN_FILE_CHOOSE_ACTIVITY); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED); + } else { + registerReceiver(broadcastReceiver, intentFilter); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(broadcastReceiver); + } + + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 114514 && resultCode == 1919810) { + if (data != null) { + Intent intent = new Intent(FILE_CHOOSE_ACTIVITY_RESULT); + intent.putExtra(FILE_CHOOSE_REAL_PATH, data.getStringExtra(CHOOSE_RESULT)); + intent.putExtra(IS_SAVE_EDIT, data.getBooleanExtra(IS_SAVE_EDIT, false)); + if (data.getBooleanExtra(IS_SAVE_EDIT, false)) { + intent.putExtra(IS_IMPORT_MIO, data.getBooleanExtra(IS_IMPORT_MIO, false)); + intent.putExtra(SAVE_EDIT_COUNT, data.getIntExtra(SAVE_EDIT_COUNT, 0)); + } + sendBroadcast(intent); + } else { + new AlertDialog.Builder(getApplicationContext()) + .setTitle("嘿嘿!!") + .setMessage("安卓崩喽!安卓崩喽!!!1111") + .show(); + } + } + } + + enum contentViewType { + MIO, + SAVE + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/SettingsActivity.java b/app/src/main/java/com/x8192bit/diyeditmobile/SettingsActivity.java new file mode 100644 index 0000000..4ab8903 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/SettingsActivity.java @@ -0,0 +1,150 @@ +package com.x8192bit.diyeditmobile; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.MenuItem; +import android.widget.Toast; + +import androidx.appcompat.app.ActionBar; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; + +import com.x8192bit.diyeditmobile.utils.CharUtils; +import com.x8192bit.diyeditmobile.utils.LocaleUtils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import x8192Bit.DIYEdit_Mobile.R; + + +public class SettingsActivity extends BaseActivity { + + public static List getAllActivities() { + List list = new ArrayList<>(); + try { + Class activityThread = Class.forName("android.app.ActivityThread"); + Method currentActivityThread = activityThread.getDeclaredMethod("currentActivityThread"); + currentActivityThread.setAccessible(true); + //获取主线程对象 + Object activityThreadObject = currentActivityThread.invoke(null); + Field mActivitiesField = activityThread.getDeclaredField("mActivities"); + mActivitiesField.setAccessible(true); + Map mActivities = (Map) mActivitiesField.get(activityThreadObject); + for (Map.Entry entry : mActivities.entrySet()) { + Object value = entry.getValue(); + Class activityClientRecordClass = value.getClass(); + Field activityField = activityClientRecordClass.getDeclaredField("activity"); + activityField.setAccessible(true); + Object o = activityField.get(value); + list.add((BaseActivity) o); + } + } catch (Exception e) { + e.printStackTrace(); + } + return list; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.settings_activity); + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.settings_fl, new SettingsFragment()) + .commit(); + } + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + } + + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + this.finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + public static class SettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.root_preferences, rootKey); + Preference maxHistoryCount = findPreference("maxHistoryCount"); + Preference cleanAllHistory = findPreference("cleanAllHistory"); + Preference openAboutDialog = findPreference("openAboutDialog"); + Preference ThemeSelect = findPreference("ThemeSelect"); + Preference LanguageSelect = findPreference("LanguageSelect"); + assert maxHistoryCount != null; + assert cleanAllHistory != null; + assert openAboutDialog != null; + assert ThemeSelect != null; + assert LanguageSelect != null; + maxHistoryCount.setOnPreferenceChangeListener(this); + ThemeSelect.setOnPreferenceChangeListener(this); + cleanAllHistory.setOnPreferenceClickListener(this); + openAboutDialog.setOnPreferenceClickListener(this); + LanguageSelect.setOnPreferenceChangeListener(this); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + String key = preference.getKey(); + if (key.equals("cleanAllHistory")) { + SharedPreferences sp = this.requireContext().getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); + sp.edit().putString("history", null).apply(); + Toast.makeText(requireContext(), R.string.cleanedKey, Toast.LENGTH_SHORT).show(); + } + if (key.equals("openAboutDialog")) { + Intent i = new Intent(this.requireContext(), AboutActivity.class); + startActivity(i); + } + return false; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + String key = preference.getKey(); + if (key.equals("maxHistoryCount")) { + if (CharUtils.isNumeric((String) newValue)) { + try { + if (Integer.parseInt((String) newValue) > 0) { + return true; + } else { + Toast.makeText(requireContext(), R.string.historyTooExtremeKey, Toast.LENGTH_SHORT).show(); + return false; + } + } catch (Exception e) { + Toast.makeText(requireContext(), R.string.historyTooExtremeKey, Toast.LENGTH_SHORT).show(); + return false; + } + } else { + Toast.makeText(requireContext(), R.string.numberRequiredKey, Toast.LENGTH_SHORT).show(); + return false; + } + } else if (key.equals("ThemeSelect")) { + MainActivity.setUIMode((String) newValue); + for (BaseActivity activity : getAllActivities()) { + activity.changeLanguage(requireContext()); + activity.invokeRecreate(); + } + return true; + } else if (key.equals("LanguageSelect")) { + for (BaseActivity activity : getAllActivities()) { + activity.changeLanguage(requireContext(), LocaleUtils.getLocaleFromString((String) newValue)); + activity.invokeRecreate(); + } + return true; + } + return false; + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/fragments/BGViewFragment.java b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/BGViewFragment.java new file mode 100644 index 0000000..7e66a81 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/BGViewFragment.java @@ -0,0 +1,354 @@ +package com.x8192bit.diyeditmobile.fragments; + +import static com.x8192bit.diyeditmobile.SaveEditActivity.FILE_CHOOSE_ACTIVITY_RESULT; +import static com.x8192bit.diyeditmobile.SaveEditActivity.FILE_CHOOSE_REAL_PATH; +import static com.x8192bit.diyeditmobile.SaveEditActivity.OPEN_FILE_CHOOSE_ACTIVITY; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.SeekBar; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.github.chrisbanes.photoview.PhotoView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.switchmaterial.SwitchMaterial; +import com.xperia64.diyedit.editors.GameEdit; +import com.xperia64.diyedit.editors.MangaEdit; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.util.Locale; +import java.util.Objects; + +import x8192Bit.DIYEdit_Mobile.R; + +public class BGViewFragment extends Fragment { + + public static final String IS_SAVE_EDIT = "com.x8192Bit.DIYEdit_Mobile.IS_SAVE_EDIT"; + private static final String ARG_NAME = "name"; + private static final String ARG_IS_GAME = "is_game"; + SwitchMaterial bp = null; + SeekBar ms = null; + private String name; + private Boolean is_game; + BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Objects.equals(intent.getAction(), FILE_CHOOSE_ACTIVITY_RESULT)) { + try { + SwitchMaterial bp = requireView().findViewById(R.id.bg_preview_sw); + SeekBar ms = requireView().findViewById(R.id.bg_manga_sb); + String path = intent.getStringExtra(FILE_CHOOSE_REAL_PATH); + EditText fileNameEdit = new EditText(getContext()); + new AlertDialog.Builder(getContext()) + .setTitle(R.string.exportFileNameSetKey) + .setCancelable(true) + .setView(fileNameEdit) + .setPositiveButton(R.string.okKey, (dialog, which) -> { + String fileName = fileNameEdit.getText().toString(); + if (!fileName.toLowerCase(Locale.US).endsWith(".png")) { + fileName += ".png"; + } + String pathName = path + "//" + fileName; + + Bitmap b; + if (is_game) { + if (!bp.isChecked()) { + b = DrawGameBG(name); + } else { + b = DrawGamePreview(name); + } + } else { + b = DrawManga(ms.getProgress(), name); + } + + try { + FileOutputStream out = new FileOutputStream(pathName); + if (b.compress(Bitmap.CompressFormat.PNG, 100, out)) { + try { + out.flush(); + out.close(); + Toast.makeText(getContext(), R.string.exportSuccessKey, Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(getContext(), R.string.exportFailedKey, Toast.LENGTH_SHORT).show(); + } + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + }).show(); + } catch (NullPointerException e) { + new androidx.appcompat.app.AlertDialog.Builder(requireContext()) + .setTitle("嘿嘿!!") + .setMessage("安卓崩喽!安卓崩喽!!!1111") + .show(); + } + } + } + }; + + public BGViewFragment() { + + } + + public static BGViewFragment newInstance(String name, Boolean is_game) { + BGViewFragment fragment = new BGViewFragment(); + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putBoolean(ARG_IS_GAME, is_game); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.bgview_fragment, container, false); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + name = getArguments().getString(ARG_NAME); + is_game = getArguments().getBoolean(ARG_IS_GAME); + } + IntentFilter intentFilter = new IntentFilter(FILE_CHOOSE_ACTIVITY_RESULT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + requireActivity().registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED); + } else { + requireActivity().registerReceiver(broadcastReceiver, intentFilter); + } + } + + @SuppressLint("SetTextI18n") + void refreshBG(View view) { + PhotoView bg = view.findViewById(R.id.bg_pv); + if (is_game) { + SwitchMaterial bp = view.findViewById(R.id.bg_preview_sw); + if (bp.isChecked()) { + bg.setImageBitmap(DrawGamePreview(name)); + } else { + bg.setImageBitmap(DrawGameBG(name)); + } + } else { + SeekBar ms = view.findViewById(R.id.bg_manga_sb); + bg.setImageBitmap(DrawManga(ms.getProgress(), name)); + } + } + + Bitmap DrawGamePreview(String name) { + Bitmap b = Bitmap.createBitmap(96, 64, Bitmap.Config.RGB_565); + Canvas c = new Canvas(b); + GameEdit e2 = new GameEdit(name); + Paint p = new Paint(); + for (int y = 0; y < 64; y++) { + for (int x = 0; x < 96; x++) { + int cc = e2.getPreviewPixel(x, y); + p.setColor(Color.rgb(r(cc), g(cc), b(cc))); + c.drawPoint(x, y, p); + x++; + } + } + return b; + } + + public Bitmap DrawGameBG(String file) { + Bitmap b = Bitmap.createBitmap(192, 128, Bitmap.Config.RGB_565); + Canvas c = new Canvas(b); + GameEdit ge = new GameEdit(file); + Paint p = new Paint(); + for (int y = 0; y < 128; y++) { + for (int x = 0; x < 192; x++) { + int cc = ge.getBackgroundPixel(x, y); + p.setColor( + cc == 0 ? Color.argb(255, 0, 0, 0) + : Color.argb(255, r(cc), g(cc), b(cc))); + c.drawPoint(x, y, p); + } + } + return b; + } + + public Bitmap DrawManga(int page, String file) { + Bitmap b = Bitmap.createBitmap(192, 128, Bitmap.Config.RGB_565); + Canvas c = new Canvas(b); + MangaEdit me = new MangaEdit(file); + Paint p = new Paint(); + for (int y = 0; y < 128; y++) { + for (int x = 0; x < 192; x++) { + if (me.getPixel((byte) page, x, y)) { + p.setColor(Color.rgb(0, 0, 0)); + } else { + p.setColor(Color.rgb(255, 255, 255)); + } + c.drawPoint(x, y, p); + } + } + return b; + } + + public int r(int b) { + switch (b) { + case 2: + case 14: + case 11: + case 3: + case 5: + return 255; + case 4: + return 198; + case 6: + return 206; + case 7: + return 16; + case 8: + return 41; + case 9: + return 8; + case 10: + return 115; + case 12: + return 128; + case 13: + return 192; + case 1: + default: + return 0; + } + } + + public int g(int b) { + switch (b) { + case 2: + return 223; + case 3: + return 174; + case 4: + return 73; + case 6: + case 8: + return 105; + case 7: + return 199; + case 9: + return 150; + case 10: + return 215; + case 11: + case 14: + return 255; + case 12: + return 128; + case 13: + return 192; + case 1: + case 5: + default: + return 0; + } + } + + public int b(int b) { + switch (b) { + case 2: + return 156; + case 3: + return 49; + case 6: + return 239; + case 7: + return 206; + case 8: + return 198; + case 9: + return 82; + case 10: + return 57; + case 11: + return 90; + case 12: + return 128; + case 13: + return 192; + case 14: + return 255; + case 1: + case 4: + case 5: + default: + return 0; + } + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + PhotoView bg = view.findViewById(R.id.bg_pv); + ms = view.findViewById(R.id.bg_manga_sb); + TextView tv = view.findViewById(R.id.bg_preview_tv); + FloatingActionButton ss = view.findViewById(R.id.bg_save_btn); + bp = view.findViewById(R.id.bg_preview_sw); + if (is_game) { + ((ViewGroup) ms.getParent()).removeView(ms); + bp.setOnClickListener(v -> { + refreshBG(requireView()); + tv.setText(bp.isChecked() ? getText(R.string.previewKey) : "BG "); + }); + bg.setImageBitmap(DrawGameBG(name)); + } else { + ((ViewGroup) bp.getParent()).removeView(bp); + ((ViewGroup) tv.getParent()).removeView(tv); + ms.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + refreshBG(requireView()); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + bg.setImageBitmap(DrawManga(0, name)); + } + ss.setOnClickListener(v -> { + Intent intent = new Intent(OPEN_FILE_CHOOSE_ACTIVITY); + intent.putExtra(IS_SAVE_EDIT, false); + requireActivity().sendBroadcast(intent); + // 事件处理请移步broadcastReceiver.onReceive + } + ); + } + + @Override + public void onDestroy() { + super.onDestroy(); + requireActivity().unregisterReceiver(broadcastReceiver); + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/fragments/FileSelectFragment.java b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/FileSelectFragment.java new file mode 100644 index 0000000..c666ad1 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/FileSelectFragment.java @@ -0,0 +1,229 @@ +package com.x8192bit.diyeditmobile.fragments; + +import static com.x8192bit.diyeditmobile.MainActivity.CHOOSE_RESULT; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.IS_IMPORT_MIO; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.IS_SAVE_EDIT; +import static com.x8192bit.diyeditmobile.fragments.SaveEditFragment.SAVE_EDIT_COUNT; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Environment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; + +import com.x8192bit.diyeditmobile.utils.SPUtils; + +import java.io.File; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +import x8192Bit.DIYEdit_Mobile.R; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link FileSelectFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class FileSelectFragment extends android.app.DialogFragment { + + public static final int CHOOSE_FILE = 0; + public static final int CHOOSE_DIRECTORY = 1; + private static final String ARG_SELECT_TYPE = "select_type"; + File CurrentPath = null; + private boolean isImportMIO; + private boolean isSaveEdit; + private int saveEditCount; + private boolean isTimeSorted; + private boolean isNormalOrder; + private boolean showHiddenFiles; + private int selectType; + public AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + File originalPath = CurrentPath; + try { + String path = (String) (((TextView) ((LinearLayout) view).getChildAt(1))).getText(); + if (path.equals("..")) { + CurrentPath = CurrentPath.getParentFile(); + } else { + CurrentPath = new File(CurrentPath.getAbsolutePath() + '/' + path); + if (CurrentPath.isFile() && selectType == CHOOSE_FILE) { + Intent intentResult = new Intent(); + intentResult.putExtra(CHOOSE_RESULT, CurrentPath.getAbsolutePath()); + intentResult.putExtra(IS_SAVE_EDIT, isSaveEdit); + if (isSaveEdit) { + intentResult.putExtra(IS_IMPORT_MIO, isImportMIO); + intentResult.putExtra(SAVE_EDIT_COUNT, saveEditCount); + } + //setResult(1919810, intentResult); + //finish(); + } + } + refreshList(getActivity().getApplicationContext(), view); + } catch (NullPointerException e) { + CurrentPath = originalPath; + } catch (Exception e) { + new AlertDialog.Builder(getActivity().getApplicationContext()) + .setTitle("What the fuck????!!") + .setMessage("GO FUCK YOURSELF!!!!!!!!!!!!!!!!!11").show(); + CurrentPath = originalPath; + } + } + }; + + // TODO 快点重构你这坨狗屎 + public FileSelectFragment() { + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param select_type Parameter 1. + * @return A new instance of fragment FileSelectFragment. + */ + public static FileSelectFragment newInstance(int select_type) { + FileSelectFragment fragment = new FileSelectFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_SELECT_TYPE, select_type); + fragment.setArguments(args); + return fragment; + } + + private static @NonNull HashMap getStringObjectHashMap(File f) { + HashMap file = new HashMap<>(); + if (f.isFile()) { + String[] split = f.getName().split("\\."); + if (f.getName().equals("MDATA") || f.getName().equals("GDATA") || f.getName().equals("RDATA")) { + file.put("img", R.drawable.save_wii); + } else if (split.length > 1 && (split[split.length - 1].equals("sav") || split[split.length - 1].equals("dsv"))) { + file.put("img", R.drawable.save_ds); + } else if (split.length > 1 && split[split.length - 1].equals("mio")) { + file.put("img", R.mipmap.ic_launcher_foreground); + } else { + file.put("img", R.drawable.baseline_file_open_24); + } + } else if (f.isDirectory()) { + file.put("img", R.drawable.directory); + } + file.put("text", f.getName()); + file.put("date", f.lastModified()); + return file; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + selectType = getArguments().getInt(ARG_SELECT_TYPE); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.file_select_fragment, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + Button selectDirectoryButton = view.findViewById(R.id.file_select_ok_btn); + + if (selectType == CHOOSE_FILE) { + // When selecting a file, the OK button is useless so remove + ((LinearLayout) view.findViewById(R.id.file_select_ll)).removeView(selectDirectoryButton); + } else { + selectDirectoryButton.setOnClickListener(v -> { + try { + Intent intentResult = new Intent(); + String path = CurrentPath.getAbsolutePath(); + intentResult.putExtra(CHOOSE_RESULT, path); + intentResult.putExtra(IS_SAVE_EDIT, isSaveEdit); + if (isSaveEdit) { + intentResult.putExtra(IS_IMPORT_MIO, isImportMIO); + intentResult.putExtra(SAVE_EDIT_COUNT, saveEditCount); + } +// setResult(1919810, intentResult); +// this.finish(); + } catch (Exception e) { + new AlertDialog.Builder(getActivity().getApplicationContext()) + .setTitle("What the fuck????!!") + .setMessage("GO FUCK YOURSELF!!!!!!!!!!!!!!!!!11").show(); + } + }); + } + + // initialize the actionbar so that we can add some button to it then +// ActionBar actionBar = getSupportActionBar(); +// if (actionBar != null) { +// actionBar.setHomeButtonEnabled(true); +// actionBar.setDisplayHomeAsUpEnabled(true); +// } + + CurrentPath = Environment.getExternalStorageDirectory(); + + ListView fileChooser = view.findViewById(R.id.file_select_lv); + + isTimeSorted = SPUtils.isTimeSorted(getActivity().getApplicationContext()); + isNormalOrder = SPUtils.isNormalOrder(getActivity().getApplicationContext()); + showHiddenFiles = SPUtils.isShowingHiddenFiles(getActivity().getApplicationContext()); + + refreshList(getActivity().getApplicationContext(), view); + + fileChooser.setOnItemClickListener(listener); + } + + public void refreshList(Context c, View view) { + ListView fileSelectView = view.findViewById(R.id.file_select_lv); + TextView PathView = view.findViewById(R.id.file_select_dir_tv); + + String[] from = {"img", "text"}; + int[] to = {R.id.file_select_item_iv, R.id.file_select_item_tv}; + + ArrayList> files = new ArrayList<>(); + + for (File f : Objects.requireNonNull(CurrentPath.listFiles())) { + if (showHiddenFiles || !f.isHidden()) { + HashMap file = getStringObjectHashMap(f); + files.add(file); + } + } + if (isTimeSorted) { + Collections.sort(files, (o1, o2) -> { + Comparator comparator = Collator.getInstance(Locale.getDefault()); + return isNormalOrder ? comparator.compare(o1.get("text"), o2.get("text")) : -comparator.compare(o1.get("text"), o2.get("text")); + }); + } else { + Collections.sort(files, (o1, o2) -> (isNormalOrder ? (long) o1.get("date") > (long) o2.get("date") ? 1 : -1 : (long) o1.get("date") > (long) o2.get("date") ? -1 : 1)); + } + HashMap parentFolder = new HashMap<>(); + parentFolder.put("img", R.drawable.exit); + parentFolder.put("text", ".."); + parentFolder.put("date", 0); + files.add(0, parentFolder); + fileSelectView.setAdapter(new SimpleAdapter(c, files, R.layout.file_select_item, from, to)); + PathView.setText(CurrentPath.getAbsolutePath()); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/fragments/MIDIFragment.java b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/MIDIFragment.java new file mode 100644 index 0000000..ed5cf0d --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/MIDIFragment.java @@ -0,0 +1,272 @@ +package com.x8192bit.diyeditmobile.fragments; + +import static com.x8192bit.diyeditmobile.fragments.MIDIFragment.egm; +import static com.x8192bit.diyeditmobile.fragments.MIDIFragment.em; +import static com.x8192bit.diyeditmobile.fragments.MIDIFragment.is_game; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.SeekBar; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RawRes; +import androidx.fragment.app.Fragment; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.xperia64.diyedit.ExportGameMidi; +import com.xperia64.diyedit.ExportMidi; +import com.xperia64.diyedit.FileByteOperations; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import x8192Bit.DIYEdit_Mobile.R; + + +public class MIDIFragment extends Fragment { + + private static final String ARG_NAME = "name"; + private static final String ARG_IS_GAME = "is_game"; + public static Boolean is_game; + static ExportMidi em; + static ExportGameMidi egm; + private String name; + private boolean playing = false; + private boolean started = false; + + public MIDIFragment() { + + } + + public static MIDIFragment newInstance(String name, Boolean is_game) { + MIDIFragment fragment = new MIDIFragment(); + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putBoolean(ARG_IS_GAME, is_game); + fragment.setArguments(args); + return fragment; + } + + public static String copyRawToTempFile(Context c, @RawRes int ResID, String prefix, String suffix) throws IOException { + InputStream is = c.getResources().openRawResource(ResID); + File f = File.createTempFile(prefix, suffix, c.getFilesDir()); + //File f = File.createTempFile(prefix, suffix, requireContext().getCacheDir()); + /* + if(f.exists()){ + //TODO + // if playable, then continue; + // if play failed, then recopy + } + + */ + try (FileOutputStream os = new FileOutputStream(f)) { + int readBytes; + byte[] buffer = new byte[4096]; + while ((readBytes = is.read(buffer)) != -1) { + os.write(buffer, 0, readBytes); + } + } + return f.getAbsolutePath(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + if (is_game) { + if (!egm.paused() && !egm.playing() && started) { + started = false; + playing = false; + } + if (started) { + egm.Stop(); + } + } else { + if (!em.paused() && !em.playing() && started) { + started = false; + playing = false; + } + if (started) { + em.Stop(); + } + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + name = getArguments().getString(ARG_NAME); + is_game = getArguments().getBoolean(ARG_IS_GAME); + } + if (is_game) { + egm = new ExportGameMidi(FileByteOperations.read(name)); + } else { + em = new ExportMidi(FileByteOperations.read(name)); + } + } + + @Deprecated + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + ImageButton stopButton = requireView().findViewById(R.id.midi_stop_btn); + ImageButton playPauseButton = requireView().findViewById(R.id.midi_play_pause_btn); + FloatingActionButton exportButton = requireView().findViewById(R.id.midi_save_btn); + SeekBar timeBar = requireView().findViewById(R.id.midi_progress_bar); + stopButton.setOnClickListener(v -> { + if (is_game) { + if (!egm.paused() && !egm.playing() && started) { + started = false; + playing = false; + } + + if (started) { + egm.Stop(); + } + } else { + if (!em.paused() && !em.playing() && started) { + started = false; + playing = false; + } + if (started) { + em.Stop(); + } + } + + playPauseButton.setImageResource(R.drawable.baseline_play_arrow_24); + }); + playPauseButton.setOnClickListener(v -> { + new PlayThread().setContext(requireContext()).start(); + + //TODO AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH + + /* TRADITIONAL SOLUTION + if (is_game) { + if (!egm.paused() && !egm.playing() && started) { + started = false; + playing = false; + } + if (!playing && !started) { + playing = true; + started = true; + playPauseButton.setImageResource(R.drawable.ic_baseline_pause_24); + new PlayThread().start(getContext(), timeBar, timeView); + + } else if (!playing && started) { + playing = true; + playPauseButton.setImageResource(R.drawable.ic_baseline_pause_24); + egm.PlayPause(); + } else if (playing) { + playing = false; + playPauseButton.setImageResource(R.drawable.ic_baseline_play_arrow_24); + egm.PlayPause(); + } + } else { + if (!em.paused() && !em.playing() && started) { + started = false; + playing = false; + } + if (!playing && !started) { + playing = true; + started = true; + playPauseButton.setImageResource(R.drawable.ic_baseline_pause_24); + new PlayThread().start(getContext(), timeBar, timeView); + + } else if (!playing && started) { + playing = true; + playPauseButton.setImageResource(R.drawable.ic_baseline_pause_24); + em.PlayPause(); + } else if (playing) { + playing = false; + playPauseButton.setImageResource(R.drawable.ic_baseline_play_arrow_24); + em.PlayPause(); + } + } + + + + */ + }); + + exportButton.setOnClickListener(v -> { + /*StorageChooser chooser = new StorageChooser.Builder() + .withActivity(getActivity()) + .withFragmentManager(requireActivity().getFragmentManager()) + .withMemoryBar(true) + .allowCustomPath(true) + .setType(StorageChooser.DIRECTORY_CHOOSER) + .build(); + chooser.show(); + chooser.setOnSelectListener(pathExtract -> { + EditText fileNameEdit = new EditText(getContext()); + new AlertDialog.Builder(getContext()) + .setTitle(R.string.exportFileNameSetKey) + .setCancelable(true) + .setView(fileNameEdit) + .setPositiveButton(R.string.okKey, (dialog, which) -> { + String fileName = fileNameEdit.getText().toString(); + if (!fileName.toLowerCase(Locale.US).endsWith(".mid")) { + fileName += ".mid"; + } + String pathName = pathExtract + "//" + fileName; + + + }) + .show(); + });*/ + }); + timeBar.setEnabled(false); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.midi_fragment, container, true); + } +} + +class PlayThread extends Thread { + + static { + System.loadLibrary("midi-interface"); + } + + Context c = null; + + public native String PlayMIDIFile(String MIDIFilePath, String SoundFontFilePath); + + public PlayThread setContext(Context context) { + c = context; + return this; + } + + @Override + public void run() { + super.run(); + try { + File f = File.createTempFile("midi", "mid", c.getCacheDir()); + if (is_game) { + egm.export(f.getAbsolutePath(), false); + } else { + em.export(f.getAbsolutePath()); + } + + // TODO: OH WE HAVE ASS(ET)LOADER NOW SO A LOT OF WORK IS NEED HERE + // AHH + + String soundFontPath = MIDIFragment.copyRawToTempFile(c, R.raw.wwdiy_soundfont, "soundfont", "sf2"); + + PlayMIDIFile(f.getAbsolutePath(), soundFontPath); + } catch (IOException e) { + throw new RuntimeException(e); + } + + + } +} diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/fragments/MetadataFragment.java b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/MetadataFragment.java new file mode 100644 index 0000000..fd38b46 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/MetadataFragment.java @@ -0,0 +1,361 @@ +package com.x8192bit.diyeditmobile.fragments; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.Spinner; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.google.android.material.switchmaterial.SwitchMaterial; +import com.google.android.material.textfield.TextInputEditText; +import com.x8192bit.diyeditmobile.utils.CharUtils; +import com.x8192bit.diyeditmobile.utils.GraphicsUtils; +import com.xperia64.diyedit.FileByteOperations; +import com.xperia64.diyedit.metadata.Checksums; +import com.xperia64.diyedit.metadata.GameMetadata; +import com.xperia64.diyedit.metadata.MangaMetadata; +import com.xperia64.diyedit.metadata.Metadata; +import com.xperia64.diyedit.metadata.RecordMetadata; + +import org.joda.time.DateTime; + +import java.util.Locale; +import java.util.Objects; + +import x8192Bit.DIYEdit_Mobile.R; + +public class MetadataFragment extends Fragment { + + private static final String ARG_NAME = "name"; + private static final String ARG_MIOTYPE = "miotype"; + + private boolean isCharLostMode = false; + + private String name; + + private int mioType; + AdapterView.OnItemSelectedListener SpinnerEvent = new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + refreshIcon(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }; + private TextView CharLostIndicator; + + public MetadataFragment() { + } + + public static MetadataFragment newInstance(String name, int mio_type) { + MetadataFragment fragment = new MetadataFragment(); + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putInt(ARG_MIOTYPE, mio_type); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + name = getArguments().getString(ARG_NAME); + mioType = getArguments().getInt(ARG_MIOTYPE); + } + } + + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.metadata_fragment, container, true); + } + + void refreshIcon() { + //region Init + Spinner selfColor = requireView().findViewById(R.id.metadata_self_color_spinner); + Spinner selfStyle = requireView().findViewById(R.id.metadata_self_style_spinner); + Spinner iconColor = requireView().findViewById(R.id.metadata_icon_color_spinner); + Spinner iconStyle = requireView().findViewById(R.id.metadata_icon_style_spinner); + ImageView preview = requireView().findViewById(R.id.metadata_icon_iv); + //endregion + //region For GAME Refresh + if (mioType == 0) { + GraphicsUtils gt = new GraphicsUtils(); + GraphicsUtils.GameItem gi = gt.new GameItem(); + gi.setCartridgeColor(selfColor.getSelectedItemPosition()); + gi.setCartridgeShape(selfStyle.getSelectedItemPosition()); + gi.setIconColor(iconColor.getSelectedItemPosition()); + gi.setIconShape(iconStyle.getSelectedItemPosition()); + preview.setImageDrawable(gi.renderImage(getContext())); + } + //endregion + //region For RECORD Refresh + else if (mioType == 1) { + GraphicsUtils gt = new GraphicsUtils(); + GraphicsUtils.RecordItem ri = gt.new RecordItem(); + ri.setRecordColor(selfColor.getSelectedItemPosition()); + ri.setRecordShape(selfStyle.getSelectedItemPosition()); + ri.setIconColor(iconColor.getSelectedItemPosition()); + ri.setIconShape(iconStyle.getSelectedItemPosition()); + preview.setImageDrawable(ri.renderImage(getContext())); + } + //endregion + //region For MANGA Refresh + else if (mioType == 2) { + GraphicsUtils gt = new GraphicsUtils(); + GraphicsUtils.MangaItem mi = gt.new MangaItem(); + mi.setMangaColor(selfColor.getSelectedItemPosition()); + mi.setIconColor(iconColor.getSelectedItemPosition()); + mi.setIconShape(iconStyle.getSelectedItemPosition()); + preview.setImageDrawable(mi.renderImage(getContext())); + } + //endregion + } + + @SuppressLint("SetTextI18n") + void loadFromFile(View view) { + //region Init + Metadata m = new Metadata(name); + TextInputEditText seriesInput = view.findViewById(R.id.metadata_serial_ti); + TextInputEditText nameInput = view.findViewById(R.id.metadata_name_ti); + TextInputEditText commentInput = view.findViewById(R.id.metadata_description_ti); + TextInputEditText authorInput = view.findViewById(R.id.metadata_author_ti); + TextInputEditText companyInput = view.findViewById(R.id.metadata_company_ti); + TextInputEditText instructInput = view.findViewById(R.id.metadata_command_ti); + TextView lockTextView = view.findViewById(R.id.metadata_lock_tv); + SwitchMaterial lockSwitch = view.findViewById(R.id.metadata_lock_sw); + TextInputEditText dateInput = view.findViewById(R.id.metadata_date_ti); + RadioButton shortButton = view.findViewById(R.id.metadata_time_short_btn); + RadioButton longButton = view.findViewById(R.id.metadata_time_long_btn); + RadioButton bossButton = view.findViewById(R.id.metadata_time_boss_btn); + Spinner selfColor = view.findViewById(R.id.metadata_self_color_spinner); + Spinner selfStyle = view.findViewById(R.id.metadata_self_style_spinner); + Spinner iconColor = view.findViewById(R.id.metadata_icon_color_spinner); + Spinner iconStyle = view.findViewById(R.id.metadata_icon_style_spinner); + selfStyle.setOnItemSelectedListener(SpinnerEvent); + selfColor.setOnItemSelectedListener(SpinnerEvent); + iconColor.setOnItemSelectedListener(SpinnerEvent); + iconStyle.setOnItemSelectedListener(SpinnerEvent); + //endregion + //region For GAME Settings + if (mioType == 0) { + GameMetadata gm = new GameMetadata(name); + instructInput.setText(gm.getCommand()); + switch (gm.getLength()) { + case 0: + shortButton.toggle(); + break; + case 1: + longButton.toggle(); + break; + case 2: + bossButton.toggle(); + break; + } + selfColor.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.diy_colors))); + selfStyle.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.game_shapes))); + iconColor.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.diy_colors))); + iconStyle.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.game_icons))); + selfColor.setSelection(gm.getCartColor()); + selfStyle.setSelection(gm.getCartType()); + iconColor.setSelection(gm.getLogoColor()); + iconStyle.setSelection(gm.getLogo()); + } else { + instructInput.setEnabled(false); + shortButton.setEnabled(false); + longButton.setEnabled(false); + bossButton.setEnabled(false); + } + //endregion + //region For RECORD Settings + if (mioType == 1) { + + selfColor.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.diy_colors))); + selfStyle.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.record_shapes))); + iconColor.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.diy_colors))); + iconStyle.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.record_icons))); + RecordMetadata rm = new RecordMetadata(name); + selfColor.setSelection(rm.getRecordColor()); + selfStyle.setSelection(rm.getRecordType()); + iconColor.setSelection(rm.getLogoColor()); + iconStyle.setSelection(rm.getLogo()); + } + //endregion + //region For MANGA Settings + if (mioType == 2) { + MangaMetadata mm = new MangaMetadata(name); + selfStyle.setEnabled(false); + selfColor.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.diy_colors))); + iconColor.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.diy_colors))); + iconStyle.setAdapter(new ArrayAdapter<>(requireContext(), R.layout.spinner_item, R.id.spinner_tv, requireContext().getResources().getTextArray(R.array.manga_icons))); + selfColor.setSelection(mm.getMangaColor()); + iconColor.setSelection(mm.getLogoColor()); + iconStyle.setSelection(mm.getLogo()); + } + //endregion + //region Overall Settings + seriesInput.setText( + m.getSerial1() + + "-" + + String.format(Locale.getDefault(), "%0" + 4 + "d", m.getSerial2()) + + "-" + + String.format(Locale.getDefault(), "%0" + 4 + "d", m.getSerial3()) + ); + nameInput.setText(m.getName()); + commentInput.setText(m.getDescription()); + authorInput.setText(m.getCreator()); + companyInput.setText(m.getBrand()); + DateTime date = new DateTime(2000, 1, 1, 0, 0, 0, 0); + date = date.plusDays(m.getTimestamp()); + String name = String.format(Locale.getDefault(), "%04d-%02d-%02d", date.getYear(), date.getMonthOfYear(), date.getDayOfMonth()); + dateInput.setText(name); + lockSwitch.setChecked(m.getLocked()); + lockTextView.setText(m.getLocked() ? R.string.lockEditKey : R.string.unlockEditKey); + //endregion + } + + + void writeToFile(View view) { + //region Init + byte[] fil = FileByteOperations.read(name); + Metadata m = new Metadata(fil); + TextInputEditText seriesInput = view.findViewById(R.id.metadata_serial_ti); + TextInputEditText nameInput = view.findViewById(R.id.metadata_name_ti); + TextInputEditText commentInput = view.findViewById(R.id.metadata_description_ti); + TextInputEditText authorInput = view.findViewById(R.id.metadata_author_ti); + TextInputEditText companyInput = view.findViewById(R.id.metadata_company_ti); + TextInputEditText instructInput = view.findViewById(R.id.metadata_command_ti); + SwitchMaterial lockSwitch = view.findViewById(R.id.metadata_lock_sw); + RadioButton shortButton = view.findViewById(R.id.metadata_time_short_btn); + RadioButton longButton = view.findViewById(R.id.metadata_time_long_btn); + RadioButton bossButton = view.findViewById(R.id.metadata_time_boss_btn); + Spinner selfColor = view.findViewById(R.id.metadata_self_color_spinner); + Spinner selfStyle = view.findViewById(R.id.metadata_self_style_spinner); + Spinner iconColor = view.findViewById(R.id.metadata_icon_color_spinner); + Spinner iconStyle = view.findViewById(R.id.metadata_icon_style_spinner); + m.setLocked(lockSwitch.isChecked()); + //endregion + //region CharLostMode Check PRE part + String pre_name = Objects.requireNonNull(nameInput.getText()).toString(); + String pre_comment = Objects.requireNonNull(commentInput.getText()).toString(); + String pre_author = Objects.requireNonNull(authorInput.getText()).toString(); + String pre_company = Objects.requireNonNull(companyInput.getText()).toString(); + String pre_command = null; + //endregion + //region Overall Settings + try { + String[] splited = Objects.requireNonNull(seriesInput.getText()).toString().split("-"); + if (splited.length != 3 || splited[0].length() > 4 || splited[1].length() > 4 || splited[2].length() > 4 || !CharUtils.isNumeric(splited[1]) || !CharUtils.isNumeric(splited[2])) { + new AlertDialog.Builder(getContext()) + .setMessage(R.string.serialNumberWrongKey) + .setCancelable(true) + .setNegativeButton(R.string.okKey, null) + .show(); + } else { + m.setSerial(splited[0], Integer.parseInt(splited[1]), Integer.parseInt(splited[2])); + m.setName(isCharLostMode ? CharUtils.doubleFirstChar(pre_name) : pre_name); + m.setDescription(isCharLostMode ? CharUtils.doubleFirstChar(pre_comment) : pre_comment); + m.setCreator(isCharLostMode ? CharUtils.doubleFirstChar(pre_author) : pre_author); + m.setBrand(isCharLostMode ? CharUtils.doubleFirstChar(pre_company) : pre_company); + } + } catch (NullPointerException e) { + e.printStackTrace(); + new AlertDialog.Builder(getContext()) + .setMessage(R.string.metadataEmptyKey) + .setCancelable(true) + .setNegativeButton(R.string.okKey, null) + .show(); + } + + fil = m.file; + //endregion + //region For GAME Settings + if (mioType == 0) { + GameMetadata gm = new GameMetadata(fil); + + pre_command = Objects.requireNonNull(instructInput.getText()).toString(); + gm.setCommand(isCharLostMode ? CharUtils.doubleFirstChar(pre_command) : pre_command); + if (shortButton.isChecked()) { + gm.setLength((byte) 0); + } else if (longButton.isChecked()) { + gm.setLength((byte) 1); + } else if (bossButton.isChecked()) { + gm.setLength((byte) 2); + } + gm.setCartColor((byte) selfColor.getSelectedItemPosition()); + gm.setCartType((byte) selfStyle.getSelectedItemPosition()); + gm.setLogoColor((byte) iconColor.getSelectedItemPosition()); + gm.setLogo((byte) iconStyle.getSelectedItemPosition()); + FileByteOperations.write(Checksums.writeChecksums(gm.file), name); + } else + //endregion + //region For RECORD Settings + if (mioType == 1) { + RecordMetadata rm = new RecordMetadata(fil); + rm.setRecordColor((byte) selfColor.getSelectedItemPosition()); + rm.setRecordType((byte) selfStyle.getSelectedItemPosition()); + rm.setLogoColor((byte) iconColor.getSelectedItemPosition()); + rm.setLogo((byte) iconStyle.getSelectedItemPosition()); + FileByteOperations.write(Checksums.writeChecksums(rm.file), name); + } else + //endregion + //region For MANGA Settings + if (mioType == 2) { + MangaMetadata mm = new MangaMetadata(fil); + mm.setMangaColor((byte) selfColor.getSelectedItemPosition()); + mm.setLogoColor((byte) iconColor.getSelectedItemPosition()); + mm.setLogo((byte) iconStyle.getSelectedItemPosition()); + FileByteOperations.write(Checksums.writeChecksums(mm.file), name); + } + //endregion + //region CharLostMode Check POST part + String post_name = m.getName(); + if (!isCharLostMode && !pre_name.equals(post_name) && pre_name.contains(post_name)) { + isCharLostMode = true; + CharLostIndicator.setText(R.string.charLostModeKey); + m.setName(CharUtils.doubleFirstChar(pre_name)); + m.setDescription(CharUtils.doubleFirstChar(pre_comment)); + m.setCreator(CharUtils.doubleFirstChar(pre_author)); + m.setBrand(CharUtils.doubleFirstChar(pre_company)); + if (mioType == 0) { + GameMetadata gm = new GameMetadata(fil); + gm.setCommand(CharUtils.doubleFirstChar(pre_command)); + FileByteOperations.write(Checksums.writeChecksums(gm.file), name); + } + + } + //endregion + FileByteOperations.write(Checksums.writeChecksums(m.file), name); + loadFromFile(view); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + loadFromFile(view); + Button save = view.findViewById(R.id.metadata_save_btn); + Button discard = view.findViewById(R.id.metadata_discard_btn); + CharLostIndicator = view.findViewById(R.id.metadata_char_lost_tv); + SwitchMaterial lockSwitch = view.findViewById(R.id.metadata_lock_sw); + lockSwitch.setOnClickListener((vl) -> { + ((TextView) view.findViewById(R.id.metadata_lock_tv)).setText(lockSwitch.isChecked() ? R.string.lockEditKey : R.string.unlockEditKey); + }); + discard.setOnClickListener((vd) -> loadFromFile(requireView())); + save.setOnClickListener((vs) -> writeToFile(requireView())); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/fragments/SaveEditFragment.java b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/SaveEditFragment.java new file mode 100644 index 0000000..14275da --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/SaveEditFragment.java @@ -0,0 +1,391 @@ +package com.x8192bit.diyeditmobile.fragments; + +import static com.x8192bit.diyeditmobile.SaveEditActivity.FILE_CHOOSE_ACTIVITY_RESULT; +import static com.x8192bit.diyeditmobile.SaveEditActivity.FILE_CHOOSE_REAL_PATH; +import static com.x8192bit.diyeditmobile.SaveEditActivity.OPEN_FILE_CHOOSE_ACTIVITY; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.PopupMenu; +import androidx.fragment.app.Fragment; + +import com.google.android.material.button.MaterialButton; +import com.x8192bit.diyeditmobile.utils.GraphicsUtils; +import com.xperia64.diyedit.FileByteOperations; +import com.xperia64.diyedit.metadata.GameMetadata; +import com.xperia64.diyedit.metadata.MangaMetadata; +import com.xperia64.diyedit.metadata.Metadata; +import com.xperia64.diyedit.metadata.RecordMetadata; +import com.xperia64.diyedit.saveutils.SaveHandler; + +import org.joda.time.DateTime; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Locale; + +import x8192Bit.DIYEdit_Mobile.R; + +public class SaveEditFragment extends Fragment { + + public static final String IS_IMPORT_MIO = "com.x8192Bit.DIYEdit_Mobile.IS_IMPORT_MIO"; + public static final String IS_SAVE_EDIT = "com.x8192Bit.DIYEdit_Mobile.IS_SAVE_EDIT"; + public static final String SAVE_EDIT_COUNT = "com.x8192Bit.DIYEdit_Mobile.SAVE_EDIT_COUNT"; + private static final String ARG_NAME = "name"; + private static final String ARG_MIO_TYPE = "mio_type"; + private String name; + private int mio_type; + private int shelfNo = 1; + private SaveItemAdapter si; + private GridView gv; + BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + SaveHandler s = new SaveHandler(name); + if (intent.getBooleanExtra(IS_IMPORT_MIO, true)) { + String pathImport = intent.getStringExtra(FILE_CHOOSE_REAL_PATH); + int count = intent.getIntExtra(SAVE_EDIT_COUNT, 0); + int length = FileByteOperations.read(pathImport).length; + int size; + switch (mio_type) { + case 0: + size = 65536; + break; + case 1: + size = 8192; + break; + case 2: + size = 14336; + break; + default: + throw new IllegalStateException("Unexpected value: " + mio_type); + } + if (length == size) { + s.setMio(pathImport, count + 18 * (shelfNo - 1)); + s.saveChanges(); + refreshShelf(); + } else { + Toast.makeText(getContext(), R.string.couldNotReadFileKey, Toast.LENGTH_SHORT).show(); + } + } else { + + String pathExtract = intent.getStringExtra(FILE_CHOOSE_REAL_PATH); + int count = intent.getIntExtra(SAVE_EDIT_COUNT, 0); + EditText fileNameEdit = new EditText(getContext()); + AlertDialog ad = new AlertDialog.Builder(getContext()) + .setTitle(R.string.exportFileNameSetKey) + .setCancelable(true) + .setView(fileNameEdit) + .setNeutralButton("默认", null) + .setPositiveButton(R.string.okKey, (dialog, which) -> { + String fileName = fileNameEdit.getText().toString(); + if (!fileName.toLowerCase(Locale.US).endsWith(".mio")) { + fileName += ".mio"; + } + String pathName = pathExtract + "//" + fileName; + try { + new File(pathName).createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + Toast.makeText(getContext(), R.string.warningKey, Toast.LENGTH_SHORT).show(); + } + FileByteOperations.write(s.getMio(mio_type, count + 18 * (shelfNo - 1)), pathName); + s.saveChanges(); + refreshShelf(); + }) + .create(); + ad.setOnShowListener(dialog -> ad + .getButton(AlertDialog.BUTTON_NEUTRAL) + .setOnClickListener(v -> { + + String key = ""; + switch (mio_type) { + case 0: + key = "G"; + break; + case 1: + key = "R"; + break; + case 2: + key = "M"; + break; + } + Metadata m = new Metadata(s.getMio(mio_type, count + 18 * (shelfNo - 1))); + + DateTime date = new DateTime(2000, 1, 1, 0, 0, 0, 0); + date = date.plusDays(m.getTimestamp()); + @SuppressLint("DefaultLocale") String name = String.format("%s-%s(%s)-%04d (%s) (%04d-%02d-%02d) %s.mio", + key, m.getCreator(), m.getBrand(), m.getSerial2(), (m.getRegion()) ? "J" : "UE", date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), (m.getLocked() ? "(#) " : "") + m.getName()); + name = name.replace('?', '¿') + .replace('/', '〳') + .replace('\\', '〳') + .replace(':', ':') + .replace('*', '★') + .replace('\"', '\'') + .replace('<', '<') + .replace('>', '>') + .replace('|', 'l') + .replace('!', '¡'); + fileNameEdit.setText(name); + })); + ad.show(); + + } + } + }; + + public SaveEditFragment() { + } + + public static SaveEditFragment newInstance(String name, int mio_type) { + SaveEditFragment fragment = new SaveEditFragment(); + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putInt(ARG_MIO_TYPE, mio_type); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + gv = requireView().findViewById(R.id.save_shelf_gv); + + MaterialButton diy1 = requireView().findViewById(R.id.save_shelf_1_btn); + MaterialButton diy2 = requireView().findViewById(R.id.save_shelf_2_btn); + MaterialButton diy3 = requireView().findViewById(R.id.save_shelf_3_btn); + MaterialButton diy4 = requireView().findViewById(R.id.save_shelf_4_btn); + MaterialButton diy5 = requireView().findViewById(R.id.save_shelf_5_btn); + int length = FileByteOperations.read(name).length; + if (length == 4719808 || length == 591040 || length == 1033408 || length == 6438592) { + ((LinearLayout) requireView().findViewById(R.id.save_shelf_select_ll)).removeView(diy5); + } else { + diy5.setOnClickListener(v -> { + shelfNo = 5; + refreshShelf(); + }); + } + diy1.setOnClickListener(v -> { + shelfNo = 1; + refreshShelf(); + }); + diy2.setOnClickListener(v -> { + shelfNo = 2; + refreshShelf(); + }); + diy3.setOnClickListener(v -> { + shelfNo = 3; + refreshShelf(); + }); + diy4.setOnClickListener(v -> { + shelfNo = 4; + refreshShelf(); + }); + refreshShelf(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + name = getArguments().getString(ARG_NAME); + mio_type = getArguments().getInt(ARG_MIO_TYPE); + } + si = new SaveItemAdapter(); + IntentFilter intentFilter = new IntentFilter(FILE_CHOOSE_ACTIVITY_RESULT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + requireActivity().registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED); + } else { + requireActivity().registerReceiver(broadcastReceiver, intentFilter); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.save_edit_fragment, container, true); + } + + public void refreshShelf() { + SaveHandler s = new SaveHandler(name); + GraphicsUtils gt = new GraphicsUtils(); + si.shelfItems.clear(); + si.titles.clear(); + if (mio_type == 0) { + for (int i = 18 * (shelfNo - 1); i < 18 * shelfNo; i++) { + GraphicsUtils.GameItem gi = gt.new GameItem(); + byte[] file = s.getMio(mio_type, i); + if (file != null) { + GameMetadata gm = new GameMetadata(file); + gi.setCartridgeColor(gm.getCartColor()); + gi.setCartridgeShape(gm.getCartType()); + gi.setIconColor(gm.getLogoColor()); + gi.setIconShape(gm.getLogo()); + si.titles.add(gm.getName()); + si.shelfItems.add(i - 18 * (shelfNo - 1), gi); + } else { + si.titles.add(""); + si.shelfItems.add(i - 18 * (shelfNo - 1), null); + } + } + } + if (mio_type == 1) { + for (int i = 18 * (shelfNo - 1); i < 18 * shelfNo; i++) { + GraphicsUtils.RecordItem gi = gt.new RecordItem(); + byte[] file = s.getMio(mio_type, i); + if (file != null) { + RecordMetadata rm = new RecordMetadata(file); + gi.setRecordColor(rm.getRecordColor()); + gi.setRecordShape(rm.getRecordType()); + gi.setIconColor(rm.getLogoColor()); + gi.setIconShape(rm.getLogo()); + si.titles.add(rm.getName()); + si.shelfItems.add(i - 18 * (shelfNo - 1), gi); + } else { + si.titles.add(""); + si.shelfItems.add(i - 18 * (shelfNo - 1), null); + } + } + } + if (mio_type == 2) { + for (int i = 18 * (shelfNo - 1); i < 18 * shelfNo; i++) { + GraphicsUtils.MangaItem gi = gt.new MangaItem(); + byte[] file = s.getMio(mio_type, i); + if (file != null) { + MangaMetadata mm = new MangaMetadata(file); + gi.setMangaColor(mm.getMangaColor()); + gi.setIconColor(mm.getLogoColor()); + gi.setIconShape(mm.getLogo()); + si.titles.add(mm.getName()); + si.shelfItems.add(i - 18 * (shelfNo - 1), gi); + } else { + si.titles.add(null); + si.shelfItems.add(i - 18 * (shelfNo - 1), null); + } + } + } + gv.setAdapter(si); + } + + @Deprecated + private void showMioPopupMenu(View view, int count) { + PopupMenu popupMenu = new PopupMenu(requireContext(), view); + popupMenu.inflate(R.menu.mio_menu); + popupMenu.setOnMenuItemClickListener(item -> { + SaveHandler s = new SaveHandler(name); + if (item.getItemId() == R.id.import_file) { + Intent intent = new Intent(OPEN_FILE_CHOOSE_ACTIVITY); + intent.putExtra(IS_SAVE_EDIT, true); + intent.putExtra(IS_IMPORT_MIO, true); + intent.putExtra(SAVE_EDIT_COUNT, count); + requireActivity().sendBroadcast(intent); + } + if (item.getItemId() == R.id.extract_file) { + Intent intent = new Intent(OPEN_FILE_CHOOSE_ACTIVITY); + intent.putExtra(IS_SAVE_EDIT, true); + intent.putExtra(IS_IMPORT_MIO, false); + intent.putExtra(SAVE_EDIT_COUNT, count); + requireActivity().sendBroadcast(intent); + } + if (item.getItemId() == R.id.delete_file) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.warningKey) + .setMessage(R.string.deleteMIOWaringKey) + .setCancelable(false) + .setPositiveButton(R.string.okKey, (dialog, which) -> { + s.deleteMio(mio_type, count + 18 * (shelfNo - 1)); + s.saveChanges(); + refreshShelf(); + }) + .setNegativeButton(R.string.backKey, null) + .show(); + } + return false; + }); + popupMenu.show(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + requireActivity().unregisterReceiver(broadcastReceiver); + } + + public class SaveItemAdapter extends BaseAdapter { + private final LayoutInflater layoutInflater; + public ArrayList shelfItems = new ArrayList<>(18); + public ArrayList titles = new ArrayList<>(); + + public SaveItemAdapter() { + layoutInflater = LayoutInflater.from(getActivity()); + // Needs to be invoked after parent activity started + } + + @Override + public int getCount() { + return shelfItems.size(); + } + + @Override + public Object getItem(int position) { + return shelfItems.get(position); + } + + @Override + public long getItemId(int position) { + return position % 6; + } + + @SuppressLint("InflateParams") + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + if (convertView == null) { + convertView = layoutInflater.inflate(R.layout.shelf_item, null); + holder = new ViewHolder(); + holder.iv = convertView.findViewById(R.id.shelf_iv); + holder.tv = convertView.findViewById(R.id.shelf_tv); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + GraphicsUtils.ShelfItem si = shelfItems.get(position); + holder.tv.setSelected(true); + if (si != null) { + holder.iv.setScaleType(ImageView.ScaleType.FIT_CENTER); + holder.iv.setImageDrawable(si.renderImage(getContext())); + holder.tv.setText(titles.get(position)); + holder.iv.setOnClickListener(v -> showMioPopupMenu(v, position)); + } else { + holder.tv.setText(R.string.nullSlotKey); + holder.iv.setOnClickListener(v -> showMioPopupMenu(v, position)); + } + return convertView; + } + + class ViewHolder { + ImageView iv; + TextView tv; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/fragments/UnlockFragment.java b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/UnlockFragment.java new file mode 100644 index 0000000..1481a03 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/fragments/UnlockFragment.java @@ -0,0 +1,98 @@ +package com.x8192bit.diyeditmobile.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.xperia64.diyedit.FileByteOperations; +import com.xperia64.diyedit.saveutils.SaveHandler; + +import x8192Bit.DIYEdit_Mobile.R; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link UnlockFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class UnlockFragment extends Fragment { + + private static final String ARG_NAME = "name"; + Button unlockGames = null; + Button unlockRecords = null; + Button unlockMangas = null; + Button unlockMedals = null; + + private String name; + + public UnlockFragment() { + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param name name of the file. + * @return A new instance of fragment UnlockFragment. + */ + public static UnlockFragment newInstance(String name) { + UnlockFragment fragment = new UnlockFragment(); + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + unlockGames = view.findViewById(R.id.unlock_game_btn); + unlockRecords = view.findViewById(R.id.unlock_record_btn); + unlockMangas = view.findViewById(R.id.unlock_manga_btn); + unlockMedals = view.findViewById(R.id.unlock_medal_btn); + unlockGames.setOnClickListener(this::unlockGame); + unlockRecords.setOnClickListener(this::unlockRecord); + unlockMangas.setOnClickListener(this::unlockManga); + unlockMedals.setOnClickListener(this::unlockMedal); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + name = getArguments().getString(ARG_NAME); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.unlock_fragment, container, false); + } + + public void unlockGame(View v) { + SaveHandler s = new SaveHandler(name); + FileByteOperations.write(s.unlockMedals(), name); + } + + public void unlockRecord(View v) { + SaveHandler s = new SaveHandler(name); + FileByteOperations.write(s.unlockMedals(), name); + } + + public void unlockManga(View v) { + SaveHandler s = new SaveHandler(name); + FileByteOperations.write(s.unlockMedals(), name); + } + + public void unlockMedal(View v) { + SaveHandler s = new SaveHandler(name); + FileByteOperations.write(s.unlockMedals(), name); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/utils/CharUtils.java b/app/src/main/java/com/x8192bit/diyeditmobile/utils/CharUtils.java new file mode 100644 index 0000000..fdfbd43 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/utils/CharUtils.java @@ -0,0 +1,19 @@ +package com.x8192bit.diyeditmobile.utils; + +public class CharUtils { + + public static boolean isNumeric(String str) { + for (int i = str.length(); --i >= 0; ) { + if (!Character.isDigit(str.charAt(i))) { + return false; + } + } + return true; + } + + public static String doubleFirstChar(String str) { + StringBuilder sb = new StringBuilder(str); + sb.insert(0, str.charAt(0)); + return sb.toString(); + } +} diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/utils/FileUtils.java b/app/src/main/java/com/x8192bit/diyeditmobile/utils/FileUtils.java new file mode 100644 index 0000000..8dc2675 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/utils/FileUtils.java @@ -0,0 +1,205 @@ +package com.x8192bit.diyeditmobile.utils; + +import android.annotation.SuppressLint; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; +import android.provider.OpenableColumns; + +import androidx.annotation.RequiresApi; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class FileUtils { + + /** + * Get filepath ( API BELOW KITKAT/ABOVE QUINCE-TART ARE SUPPORTED ) + * + * @param context the context. + * @param imageUri the URI needed to translate to filepath. + */ + public static String getFileAbsolutePath(Context context, Uri imageUri) { + + if (context == null || imageUri == null) { + return null; + } + + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) { + return getRealFilePath(context, imageUri); + } + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && DocumentsContract.isDocumentUri(context, imageUri)) { + if (isExternalStorageDocument(imageUri)) { + String docId = DocumentsContract.getDocumentId(imageUri); + String[] split = docId.split(":"); + String type = split[0]; + if ("primary".equalsIgnoreCase(type)) { // TODO I USED TO COMMENTED THIS LINE + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } // TODO AND THIS LINE + } else if (isDownloadsDocument(imageUri)) { + String id = DocumentsContract.getDocumentId(imageUri); + Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + return getDataColumn(context, contentUri, null, null); + } else if (isMediaDocument(imageUri)) { + String docId = DocumentsContract.getDocumentId(imageUri); + String[] split = docId.split(":"); + String type = split[0]; + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + String selection = MediaStore.Images.Media._ID + "=?"; + String[] selectionArgs = new String[]{split[1]}; + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } // MediaStore (and general) + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return uriToFileApiQ(context, imageUri); + } else if ("content".equalsIgnoreCase(imageUri.getScheme())) { + // Return the remote address + if (isGooglePhotosUri(imageUri)) { + return imageUri.getLastPathSegment(); + } + return getDataColumn(context, imageUri, null, null); + } + // File + else if ("file".equalsIgnoreCase(imageUri.getScheme())) { + return imageUri.getPath(); + } + return null; + } + + // FOR BELOW KITKAT + private static String getRealFilePath(final Context context, final Uri uri) { + if (null == uri) { + return null; + } + final String scheme = uri.getScheme(); + String data = null; + if (scheme == null) { + data = uri.getPath(); + } else if (ContentResolver.SCHEME_FILE.equals(scheme)) { + data = uri.getPath(); + } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { + String[] projection = {MediaStore.Images.ImageColumns.DATA}; + Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); + +// Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); + if (null != cursor) { + if (cursor.moveToFirst()) { + int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); + if (index > -1) { + data = cursor.getString(index); + } + } + cursor.close(); + } + } + return data; + } + + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + private static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + private static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + Cursor cursor = null; + String column = MediaStore.Images.Media.DATA; + String[] projection = {column}; + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + int index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(index); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + private static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is Google Photos. + */ + private static boolean isGooglePhotosUri(Uri uri) { + return "com.google.android.apps.photos.content".equals(uri.getAuthority()); + } + + + /** + * FOR ABOVE QUINCE-TART(10) + * + * @param context + * @param uri + * @return + */ + @RequiresApi(api = Build.VERSION_CODES.Q) + private static String uriToFileApiQ(Context context, Uri uri) { + File file = null; + //android10以上转换 + if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) { + file = new File(uri.getPath()); + } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { + //把文件复制到沙盒目录 + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(uri, null, null, null, null); + if (cursor.moveToFirst()) { + @SuppressLint("Range") + String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + try { + InputStream is = contentResolver.openInputStream(uri); + File cache = new File(context.getExternalCacheDir().getAbsolutePath(), Math.round((Math.random() + 1) * 1000) + displayName); + FileOutputStream fos = new FileOutputStream(cache); + android.os.FileUtils.copy(is, fos); + file = cache; + fos.close(); + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }//TODO 改!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + return file.getAbsolutePath(); + + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/utils/GraphicsUtils.java b/app/src/main/java/com/x8192bit/diyeditmobile/utils/GraphicsUtils.java new file mode 100644 index 0000000..731c319 --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/utils/GraphicsUtils.java @@ -0,0 +1,541 @@ +package com.x8192bit.diyeditmobile.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; + +import java.io.InputStream; + +import x8192Bit.DIYEdit_Mobile.R; + +public class GraphicsUtils { + + public final int YELLOW = 0; + public final int LIGHTBLUE = 1; + public final int GREEN = 2; + public final int ORANGE = 3; + public final int DARKBLUE = 4; + public final int RED = 5; + public final int WHITE = 6; + public final int BLACK = 7; + + public final int RR_CIRCLE = 0; + public final int RR_SQUARE = 1; + public final int RR_STAR = 2; + public final int RR_HEXAGON = 3; + public final int RR_CLOVER = 4; + public final int RR_DIAMOND = 5; + public final int RR_PLUS = 6; + public final int RR_FLOWER = 7; + + public final int RI_HEART = 0; + public final int RI_FLOWER = 1; + public final int RI_STORM = 2; + public final int RI_CROSS = 3; + public final int RI_LEAF = 4; + public final int RI_DROPLET = 5; + public final int RI_LIGHTNING = 6; + public final int RI_SMILE = 7; + + public final int GI_PULSE = 0; + public final int GI_ROCKET = 1; + public final int GI_SHIELD = 2; + public final int GI_PUNCH = 3; + public final int GI_CAR = 4; + public final int GI_BAT = 5; + public final int GI_WHAT = 6; + public final int GI_OTHER = 7; + + public final int GG_ROUND = 0; + public final int GG_NOTCH = 1; + public final int GG_FLAT = 2; + public final int GG_RIDGES = 3; + public final int GG_ZIGZAG = 4; + public final int GG_PRONGS = 5; + public final int GG_ANGLED = 6; + public final int GG_GBA = 7; + public final int GG_BIGNAME = 8; + // maybe the same as com.xperia64.diyedit.metadata.gamemetadata.getCartType() + + public final int CI_LETTER = 0; + public final int CI_HOUSE = 1; + public final int CI_SHIELD = 2; + public final int CI_SKULL = 3; + public final int CI_CAT = 4; + public final int CI_BAT = 5; + public final int CI_SPACESHIP = 6; + public final int CI_SMILE = 7; + + public int getDIYColor(int dc) { + switch (dc) { + case YELLOW: + return 0xFFFFFF5A; + case LIGHTBLUE: + return 0xFF10C6CE; + case GREEN: + return 0xFF089452; + case ORANGE: + return 0xFFFFAD31; + case DARKBLUE: + return 0xFF296BC6; + case RED: + return 0xFFFF0000; + case WHITE: + return 0xFFFFFFFF; + case BLACK: + return 0xFF000000; + default: + return -1; + } + } + + public int getDIYSecondaryColor(int dc) { + switch (dc) { + case YELLOW: + return 0xFFF7F752; + case LIGHTBLUE: + return 0xFF84E7EF; + case GREEN: + return 0xFF10CE73; + case ORANGE: + return 0xFFEF9C21; + case DARKBLUE: + return 0xFF4A94EF; + case RED: + return 0xFFFF7373; + case WHITE: + return 0xFFFFFFFF; + case BLACK: + return 0xFF737373; + default: + return -1; + } + } + + public int getCartridgeIconID(boolean isReversed, int iconShape) { + + if (isReversed) { + switch (iconShape) { + case GI_PULSE: + return R.drawable.spr_cart_logo1_r; + case GI_ROCKET: + return R.drawable.spr_cart_logo2_r; + case GI_SHIELD: + return R.drawable.spr_cart_logo3_r; + case GI_PUNCH: + return R.drawable.spr_cart_logo4_r; + case GI_CAR: + return R.drawable.spr_cart_logo5_r; + case GI_BAT: + return R.drawable.spr_cart_logo6_r; + case GI_WHAT: + return R.drawable.spr_cart_logo7_r; + case GI_OTHER: + return R.drawable.spr_cart_logo8_r; + default: + throw new IllegalStateException("Unexpected value: " + iconShape); + } + } else { + switch (iconShape) { + case GI_PULSE: + return R.drawable.spr_cart_logo1; + case GI_ROCKET: + return R.drawable.spr_cart_logo2; + case GI_SHIELD: + return R.drawable.spr_cart_logo3; + case GI_PUNCH: + return R.drawable.spr_cart_logo4; + case GI_CAR: + return R.drawable.spr_cart_logo5; + case GI_BAT: + return R.drawable.spr_cart_logo6; + case GI_WHAT: + return R.drawable.spr_cart_logo7; + case GI_OTHER: + return R.drawable.spr_cart_logo8; + default: + throw new IllegalStateException("Unexpected value: " + iconShape); + } + } + } + + public int getCartridgeShapeID(int cartridgeShape) { + switch (cartridgeShape) { + case GG_ROUND: + return R.drawable.spr_cart1; + case GG_NOTCH: + return R.drawable.spr_cart2; + case GG_FLAT: + return R.drawable.spr_cart3; + case GG_RIDGES: + return R.drawable.spr_cart4; + case GG_ZIGZAG: + return R.drawable.spr_cart5; + case GG_PRONGS: + return R.drawable.spr_cart6; + case GG_ANGLED: + return R.drawable.spr_cart7; + case GG_GBA: + return R.drawable.spr_cart8; + case GG_BIGNAME: + return R.drawable.spr_cart9; + default: + throw new IllegalStateException("Unexpected value: " + cartridgeShape); + } + } + + + public Bitmap getBitmapFromID(Context ctx, int ID) { + InputStream is = ctx.getResources().openRawResource(ID); + return BitmapFactory.decodeStream(is).copy(Bitmap.Config.ARGB_8888, true); + } + + public int getRecordShapeID(int recordShape) { + switch (recordShape) { + case RR_CIRCLE: + return R.drawable.spr_record1; + case RR_SQUARE: + return R.drawable.spr_record2; + case RR_STAR: + return R.drawable.spr_record3; + case RR_HEXAGON: + return R.drawable.spr_record4; + case RR_CLOVER: + return R.drawable.spr_record5; + case RR_DIAMOND: + return R.drawable.spr_record6; + case RR_PLUS: + return R.drawable.spr_record7; + case RR_FLOWER: + return R.drawable.spr_record8; + default: + throw new IllegalStateException("Unexpected value: " + recordShape); + } + } + + public int getRecordIconID(boolean isReversed, int iconShape) { + if (isReversed) { + switch (iconShape) { + case RI_HEART: + return R.drawable.spr_record_logo1_r; + case RI_FLOWER: + return R.drawable.spr_record_logo2_r; + case RI_STORM: + return R.drawable.spr_record_logo3_r; + case RI_CROSS: + return R.drawable.spr_record_logo4_r; + case RI_LEAF: + return R.drawable.spr_record_logo5_r; + case RI_DROPLET: + return R.drawable.spr_record_logo6_r; + case RI_LIGHTNING: + return R.drawable.spr_record_logo7_r; + case RI_SMILE: + return R.drawable.spr_record_logo8_r; + default: + throw new IllegalStateException("Unexpected value: " + iconShape); + } + } else { + switch (iconShape) { + case RI_HEART: + return R.drawable.spr_record_logo1; + case RI_FLOWER: + return R.drawable.spr_record_logo2; + case RI_STORM: + return R.drawable.spr_record_logo3; + case RI_CROSS: + return R.drawable.spr_record_logo4; + case RI_LEAF: + return R.drawable.spr_record_logo5; + case RI_DROPLET: + return R.drawable.spr_record_logo6; + case RI_LIGHTNING: + return R.drawable.spr_record_logo7; + case RI_SMILE: + return R.drawable.spr_record_logo8; + default: + throw new IllegalStateException("Unexpected value: " + iconShape); + } + } + } + + int getMangaIconID(boolean isReversed, int iconShape) { + if (isReversed) { + switch (iconShape) { + case CI_LETTER: + return R.drawable.spr_manga_logo1_r; + case CI_HOUSE: + return R.drawable.spr_manga_logo2_r; + case CI_SHIELD: + return R.drawable.spr_manga_logo3_r; + case CI_SKULL: + return R.drawable.spr_manga_logo4_r; + case CI_CAT: + return R.drawable.spr_manga_logo5_r; + case CI_BAT: + return R.drawable.spr_manga_logo6_r; + case CI_SPACESHIP: + return R.drawable.spr_manga_logo7_r; + case CI_SMILE: + return R.drawable.spr_manga_logo8_r; + default: + throw new IllegalStateException("Unexpected value: " + iconShape); + } + } else { + switch (iconShape) { + case CI_LETTER: + return R.drawable.spr_manga_logo1; + case CI_HOUSE: + return R.drawable.spr_manga_logo2; + case CI_SHIELD: + return R.drawable.spr_manga_logo3; + case CI_SKULL: + return R.drawable.spr_manga_logo4; + case CI_CAT: + return R.drawable.spr_manga_logo5; + case CI_BAT: + return R.drawable.spr_manga_logo6; + case CI_SPACESHIP: + return R.drawable.spr_manga_logo7; + case CI_SMILE: + return R.drawable.spr_manga_logo8; + default: + throw new IllegalStateException("Unexpected value: " + iconShape); + } + } + } + + public abstract class ShelfItem { + public abstract Drawable renderImage(Context ctx); + } + + public class GameItem extends ShelfItem { + int cartridgeColor; + int cartridgeShape; + int iconColor; + int iconShape; + + + //region getters and setters + public int getCartridgeColor() { + return cartridgeColor; + } + + public void setCartridgeColor(int cartridgeColor) { + this.cartridgeColor = cartridgeColor; + } + + public int getCartridgeShape() { + return cartridgeShape; + } + + public void setCartridgeShape(int cartridgeShape) { + this.cartridgeShape = cartridgeShape; + } + + public int getIconColor() { + return iconColor; + } + + public void setIconColor(int iconColor) { + this.iconColor = iconColor; + } + + public int getIconShape() { + return iconShape; + } + + public void setIconShape(int iconShape) { + this.iconShape = iconShape; + } + + //endregion + @Override + public Drawable renderImage(Context ctx) { + Bitmap plane = Bitmap.createBitmap(28, 23, Bitmap.Config.ARGB_8888); + Paint p = new Paint(); + Canvas PlaneCanvas = new Canvas(plane); + int left = 2; + int top = 2; + plane.eraseColor(0x00FFFFFF); + boolean isIconColorRender = true; + + // SET ICON OFFSET + switch (cartridgeShape) { + case GG_NOTCH: + top = 4; + break; + case GG_GBA: + left = 3; + break; + case GG_BIGNAME: + isIconColorRender = false; + break; + } + + //Draw Cart + Bitmap Cartridge = getBitmapFromID(ctx, getCartridgeShapeID(cartridgeShape)); + Canvas CartridgeCanvas = new Canvas(Cartridge); + if (isIconColorRender) { + if (cartridgeColor == BLACK) { + CartridgeCanvas.drawColor(getDIYColor(cartridgeColor), PorterDuff.Mode.MULTIPLY); + } else { + CartridgeCanvas.drawColor(getDIYColor(cartridgeColor), PorterDuff.Mode.MULTIPLY); + } + } + PlaneCanvas.drawBitmap(Cartridge, 0, 0, p); + + if (isIconColorRender) { + //Draw Icon + Bitmap Icon = getBitmapFromID(ctx, getCartridgeIconID(cartridgeColor == iconColor, iconShape)); + Canvas IconCanvas = new Canvas(Icon); + if (iconColor == BLACK) { + IconCanvas.drawColor(getDIYColor(iconColor), PorterDuff.Mode.LIGHTEN); + } else { + IconCanvas.drawColor(getDIYColor(iconColor), PorterDuff.Mode.MULTIPLY); + } + PlaneCanvas.drawBitmap(Icon, left, top, p); + } + + BitmapDrawable d = new BitmapDrawable(plane); + d.setAntiAlias(false); + + return d; + } + + } + + public class RecordItem extends ShelfItem { + + int recordColor; + int recordShape; + int iconColor; + int iconShape; + + //region getters and setters + + public int getRecordColor() { + return recordColor; + } + + public void setRecordColor(int recordColor) { + this.recordColor = recordColor; + } + + public int getRecordShape() { + return recordShape; + } + + public void setRecordShape(int recordShape) { + this.recordShape = recordShape; + } + + public int getIconColor() { + return iconColor; + } + + public void setIconColor(int iconColor) { + this.iconColor = iconColor; + } + + public int getIconShape() { + return iconShape; + } + + public void setIconShape(int iconShape) { + this.iconShape = iconShape; + } + + //endregion + + @Override + public Drawable renderImage(Context ctx) { + Bitmap plane = Bitmap.createBitmap(26, 26, Bitmap.Config.ARGB_8888); + Paint p = new Paint(); + Canvas PlaneCanvas = new Canvas(plane); + plane.eraseColor(0x00FFFFFF); + + //Draw Record + Bitmap Record = getBitmapFromID(ctx, getRecordShapeID(recordShape)); + Canvas RecordCanvas = new Canvas(Record); + RecordCanvas.drawColor(getDIYColor(recordColor), PorterDuff.Mode.MULTIPLY); + PlaneCanvas.drawBitmap(Record, 0, 0, p); + + //Draw Icon + Bitmap Icon = getBitmapFromID(ctx, getRecordIconID(recordColor == iconColor, iconShape)); + Canvas IconCanvas = new Canvas(Icon); + IconCanvas.drawColor(getDIYColor(iconColor), PorterDuff.Mode.MULTIPLY); + PlaneCanvas.drawBitmap(Icon, 5, 5, p); + + BitmapDrawable d = new BitmapDrawable(plane); + d.setAntiAlias(false); + return d; + } + } + + public class MangaItem extends ShelfItem { + + int mangaColor; + int iconColor; + int iconShape; + + //region getters and setters + public int getMangaColor() { + return mangaColor; + } + + public void setMangaColor(int mangaColor) { + this.mangaColor = mangaColor; + } + + public int getIconColor() { + return iconColor; + } + + public void setIconColor(int iconColor) { + this.iconColor = iconColor; + } + + public int getIconShape() { + return iconShape; + } + + public void setIconShape(int iconShape) { + this.iconShape = iconShape; + } + //endregion + + @Override + public Drawable renderImage(Context ctx) { + Bitmap plane = Bitmap.createBitmap(26, 26, Bitmap.Config.ARGB_8888); + Paint p = new Paint(); + Canvas PlaneCanvas = new Canvas(plane); + plane.eraseColor(0x00FFFFFF); + + //Draw Manga + Bitmap Manga = getBitmapFromID(ctx, R.drawable.spr_manga); + Canvas MangaCanvas = new Canvas(Manga); + MangaCanvas.drawColor(getDIYColor(mangaColor), PorterDuff.Mode.MULTIPLY); + PlaneCanvas.drawBitmap(Manga, 0, 0, p); + + //Draw Icon + Bitmap Icon = getBitmapFromID(ctx, getMangaIconID(mangaColor == iconColor, iconShape)); + Canvas IconCanvas = new Canvas(Icon); + IconCanvas.drawColor(getDIYColor(iconColor), PorterDuff.Mode.MULTIPLY); + PlaneCanvas.drawBitmap(Icon, 5, 5, p); + + BitmapDrawable d = new BitmapDrawable(plane); + d.setAntiAlias(false); + + return d; + } + } + + // yes i copied them + // especially manga_item, the top and left are COMPLETELY SAME AS RECORD_ITEM!!!!!!!!!!! +} diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/utils/LocaleUtils.java b/app/src/main/java/com/x8192bit/diyeditmobile/utils/LocaleUtils.java new file mode 100644 index 0000000..be6e2dd --- /dev/null +++ b/app/src/main/java/com/x8192bit/diyeditmobile/utils/LocaleUtils.java @@ -0,0 +1,16 @@ +package com.x8192bit.diyeditmobile.utils; + +import java.util.Locale; + +public class LocaleUtils { + + public static Locale getLocaleFromString(String locale) { + if (!locale.equals("system")) { + String[] str = locale.split("-"); + return new Locale(str[0], str[1]); + } else { + return Locale.getDefault(); + } + } + +} diff --git a/app/src/main/java/com/x8192bit/diyeditmobile/utils/SPUtils.java b/app/src/main/java/com/x8192bit/diyeditmobile/utils/SPUtils.java index 992cf07..2eb3979 100644 --- a/app/src/main/java/com/x8192bit/diyeditmobile/utils/SPUtils.java +++ b/app/src/main/java/com/x8192bit/diyeditmobile/utils/SPUtils.java @@ -1,9 +1,82 @@ package com.x8192bit.diyeditmobile.utils; +import static android.content.Context.MODE_PRIVATE; + +import android.content.Context; +import android.content.SharedPreferences; + +import java.util.Locale; + public class SPUtils { - public static String getTheme() { - return "Stub!"; + private final static String sharedPreferencesName = "com.x8192Bit.DIYEdit_Mobile_preferences"; + + public static Locale getLocale(Context context) { + SharedPreferences sp = context.getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); + String locale = sp.getString("LanguageSelect", "system"); + return LocaleUtils.getLocaleFromString(locale); + } + + public static boolean isTimeSorted(Context context) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + return sp.getBoolean("isTimeSorted", false); + } + + public static boolean isNormalOrder(Context context) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + return sp.getBoolean("isNormalOrder", false); + } + + public static boolean isShowingHiddenFiles(Context context) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + return sp.getBoolean("showHiddenFiles", false); + } + + public static void setTimeSorted(Context context, boolean isTimeSorted) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + sp.edit().putBoolean("isTimeSorted", isTimeSorted).apply(); } + public static void setNormalOrder(Context context, boolean isNormalOrder) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + sp.edit().putBoolean("isNormalOrder", isNormalOrder).apply(); + } + + public static void setShowingHiddenFiles(Context context, boolean isShowingHiddenFiles) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + sp.edit().putBoolean("showHiddenFiles", isShowingHiddenFiles).apply(); + } + + public static String getTheme(Context context) { + SharedPreferences sp = context.getSharedPreferences(sharedPreferencesName, MODE_PRIVATE); + return sp.getString("ThemeSelect", "system"); + } + + private static Boolean isFullFilePath(Context context) { + SharedPreferences sp = context.getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); + return sp.getBoolean("showFullPath", false); + } + + public static String[] getHistoryItems(Context context) { + SharedPreferences sp = context.getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); + String history = sp.getString("history", null); + String[] paths = history.split(","); + if (isFullFilePath(context)) { + return paths; + } else { + String[] items = new String[paths.length]; + for (int i = 0; i < items.length; i++) { + String[] slashSplit = paths[i].split("/"); + items[i] = slashSplit[slashSplit.length - 1]; + } + return items; + } + } + + public static String[] getHistoryPaths(Context context) { + SharedPreferences sp = context.getSharedPreferences("com.x8192Bit.DIYEdit_Mobile_preferences", MODE_PRIVATE); + String history = sp.getString("history", null); + String[] paths = history.split(","); + return paths; + } } diff --git a/app/src/main/res/layout/file_select_fragment.xml b/app/src/main/res/layout/file_select_fragment.xml new file mode 100644 index 0000000..6f1c34c --- /dev/null +++ b/app/src/main/res/layout/file_select_fragment.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + +