1. Update to SMAPI 3.7.3.3
2. Remove BSPatch and ButterKnife lib
This commit is contained in:
parent
8b801247a4
commit
327e2520c5
|
@ -12,8 +12,8 @@ android {
|
|||
applicationId "com.zane.smapiinstaller"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 53
|
||||
versionName "1.6.1"
|
||||
versionCode 55
|
||||
versionName "1.6.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
|
@ -52,6 +52,10 @@ android {
|
|||
enableSplit = false
|
||||
}
|
||||
}
|
||||
|
||||
viewBinding {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
greendao {
|
||||
|
@ -61,10 +65,10 @@ greendao {
|
|||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||
implementation "androidx.navigation:navigation-fragment:2.3.0"
|
||||
implementation "androidx.navigation:navigation-ui:2.3.0"
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
|
@ -74,16 +78,13 @@ dependencies {
|
|||
implementation 'com.afollestad.material-dialogs:input:3.3.0'
|
||||
implementation 'com.afollestad.material-dialogs:lifecycle:3.3.0'
|
||||
implementation 'com.lmntrx.android.library.livin.missme:missme:0.1.5'
|
||||
// https://mvnrepository.com/artifact/com.jakewharton/butterknife
|
||||
implementation 'com.jakewharton:butterknife:10.2.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
|
||||
// https://mvnrepository.com/artifact/com.google.guava/guava
|
||||
implementation group: 'com.google.guava', name: 'guava', version: '28.2-android'
|
||||
// https://mvnrepository.com/artifact/org.zeroturnaround/zt-zip
|
||||
implementation group: 'org.zeroturnaround', name: 'zt-zip', version: '1.14'
|
||||
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
|
||||
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.9'
|
||||
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
|
||||
// https://mvnrepository.com/artifact/commons-io/commons-io
|
||||
implementation group: 'commons-io', name: 'commons-io', version: '2.7'
|
||||
implementation 'com.lzy.net:okgo:3.0.4'
|
||||
|
@ -99,8 +100,8 @@ dependencies {
|
|||
api 'org.greenrobot:greendao-generator:3.3.0'
|
||||
|
||||
testImplementation 'junit:junit:4.13'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
|
||||
def appCenterSdkVersion = '3.0.0'
|
||||
|
@ -110,6 +111,4 @@ dependencies {
|
|||
compileOnly 'org.projectlombok:lombok:1.18.12'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.12'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||
|
||||
api 'com.smart.library.util:bspatch:0.0.2'
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,29 +1,29 @@
|
|||
{
|
||||
"version": 27,
|
||||
"version": 28,
|
||||
"contents": [
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI for 1.4.5.137",
|
||||
"assetPath": "compat/137/",
|
||||
"description": "SMAPI compat package for game 1.4.4.128 - 1.4.5.137, SMAPI 3.3.2.0",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137.zip",
|
||||
"hash": "bd16e8e4cb52d636e24c6a2d2309b66a60e492d2b97c1b8f6a519c04ac42ebdc"
|
||||
"description": "SMAPI compat package for game 1.4.4.128 - 1.4.5.137, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137_2.zip",
|
||||
"hash": "3607a1f0647d49963a9803cc0445bba23a19b3c92c3b747eb12569fdb5d9b95e"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI for Galaxy Store",
|
||||
"assetPath": "compat/samsung_138/",
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_21.zip",
|
||||
"hash": "a77e8d35e0d1118bd03acda038ba00c4e13adc5eb73ebf8c200dfacdf85ef0a1"
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_22.zip",
|
||||
"hash": "e17f369ed84b2d30e6f552d27d7a06c7026a5ddf1de4552c86f31bbff6088ed9"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI for Amazon Store",
|
||||
"assetPath": "compat/amazon_138/",
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_11.zip",
|
||||
"hash": "f792ea943d2892b9c6c1116eec05916577f5f0385730a61a3d80d5d5b65b6c7d"
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_12.zip",
|
||||
"hash": "a7746738ee384d2142c2d3075a400d93f95c84bae2d56ce0e84894f24307d7a2"
|
||||
},
|
||||
{
|
||||
"type": "LOCALE",
|
||||
|
|
|
@ -5,25 +5,25 @@
|
|||
"type": "COMPAT",
|
||||
"name": "SMAPI for 1.4.5.137",
|
||||
"assetPath": "compat/137/",
|
||||
"description": "SMAPI compat package for game 1.4.4.128 - 1.4.5.137, SMAPI 3.3.2.0",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137.zip",
|
||||
"hash": "bd16e8e4cb52d636e24c6a2d2309b66a60e492d2b97c1b8f6a519c04ac42ebdc"
|
||||
"description": "SMAPI compat package for game 1.4.4.128 - 1.4.5.137, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137_2.zip",
|
||||
"hash": "3607a1f0647d49963a9803cc0445bba23a19b3c92c3b747eb12569fdb5d9b95e"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI for Galaxy Store",
|
||||
"assetPath": "compat/samsung_138/",
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_21.zip",
|
||||
"hash": "a77e8d35e0d1118bd03acda038ba00c4e13adc5eb73ebf8c200dfacdf85ef0a1"
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_22.zip",
|
||||
"hash": "e17f369ed84b2d30e6f552d27d7a06c7026a5ddf1de4552c86f31bbff6088ed9"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI for Amazon Store",
|
||||
"assetPath": "compat/amazon_138/",
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_11.zip",
|
||||
"hash": "f792ea943d2892b9c6c1116eec05916577f5f0385730a61a3d80d5d5b65b6c7d"
|
||||
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_12.zip",
|
||||
"hash": "a7746738ee384d2142c2d3075a400d93f95c84bae2d56ce0e84894f24307d7a2"
|
||||
},
|
||||
{
|
||||
"type": "LOCALE",
|
||||
|
|
|
@ -5,25 +5,25 @@
|
|||
"type": "COMPAT",
|
||||
"name": "SMAPI untuk 1.4.5.137",
|
||||
"assetPath": "compat/137/",
|
||||
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.128 - 1.4.5.137, SMAPI 3.3.2.0",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137.zip",
|
||||
"hash": "bd16e8e4cb52d636e24c6a2d2309b66a60e492d2b97c1b8f6a519c04ac42ebdc"
|
||||
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.128 - 1.4.5.137, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137_2.zip",
|
||||
"hash": "3607a1f0647d49963a9803cc0445bba23a19b3c92c3b747eb12569fdb5d9b95e"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI untuk Galaxy Store",
|
||||
"assetPath": "compat/samsung_138/",
|
||||
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_21.zip",
|
||||
"hash": "a77e8d35e0d1118bd03acda038ba00c4e13adc5eb73ebf8c200dfacdf85ef0a1"
|
||||
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_22.zip",
|
||||
"hash": "e17f369ed84b2d30e6f552d27d7a06c7026a5ddf1de4552c86f31bbff6088ed9"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI untuk Amazon Store",
|
||||
"assetPath": "compat/amazon_138/",
|
||||
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_11.zip",
|
||||
"hash": "f792ea943d2892b9c6c1116eec05916577f5f0385730a61a3d80d5d5b65b6c7d"
|
||||
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_12.zip",
|
||||
"hash": "a7746738ee384d2142c2d3075a400d93f95c84bae2d56ce0e84894f24307d7a2"
|
||||
},
|
||||
{
|
||||
"type": "LOCAL",
|
||||
|
|
|
@ -5,25 +5,25 @@
|
|||
"type": "COMPAT",
|
||||
"name": "SMAPI สำหรับ 1.4.5.137",
|
||||
"assetPath": "compat/137/",
|
||||
"description": "แพคเกจแอพลิเคชั่น SMAPI สำหรับเกม Stardew Valley เวอร์ชั่น 1.4.4.128 - 1.4.5.137, SMAPI 3.3.2.0",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137.zip",
|
||||
"hash": "bd16e8e4cb52d636e24c6a2d2309b66a60e492d2b97c1b8f6a519c04ac42ebdc"
|
||||
"description": "แพคเกจแอพลิเคชั่น SMAPI สำหรับเกม Stardew Valley เวอร์ชั่น 1.4.4.128 - 1.4.5.137, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137_2.zip",
|
||||
"hash": "3607a1f0647d49963a9803cc0445bba23a19b3c92c3b747eb12569fdb5d9b95e"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI สำหรับ Galaxy Store",
|
||||
"assetPath": "compat/samsung_138/",
|
||||
"description": "แพคเกจแอพลิเคชั่น SMAPI สำหรับเกม Stardew Valley เวอร์ชั่น 1.4.4.138 - ล่าสุด, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_21.zip",
|
||||
"hash": "a77e8d35e0d1118bd03acda038ba00c4e13adc5eb73ebf8c200dfacdf85ef0a1"
|
||||
"description": "แพคเกจแอพลิเคชั่น SMAPI สำหรับเกม Stardew Valley เวอร์ชั่น 1.4.4.138 - ล่าสุด, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_22.zip",
|
||||
"hash": "e17f369ed84b2d30e6f552d27d7a06c7026a5ddf1de4552c86f31bbff6088ed9"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI สำหรับ Amazon Store",
|
||||
"assetPath": "compat/amazon_138/",
|
||||
"description": "แพคเกจแอพลิเคชั่น SMAPI สำหรับเกม Stardew Valley เวอร์ชั่น 1.4.4.138 - ล่าสุด, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_11.zip",
|
||||
"hash": "f792ea943d2892b9c6c1116eec05916577f5f0385730a61a3d80d5d5b65b6c7d"
|
||||
"description": "แพคเกจแอพลิเคชั่น SMAPI สำหรับเกม Stardew Valley เวอร์ชั่น 1.4.4.138 - ล่าสุด, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_12.zip",
|
||||
"hash": "a7746738ee384d2142c2d3075a400d93f95c84bae2d56ce0e84894f24307d7a2"
|
||||
},
|
||||
{
|
||||
"type": "LOCALE",
|
||||
|
|
|
@ -5,25 +5,25 @@
|
|||
"type": "COMPAT",
|
||||
"name": "SMAPI兼容包 1.4.5.137",
|
||||
"assetPath": "compat/137/",
|
||||
"description": "SMAPI兼容包, 适用版本1.4.4.128 - 1.4.5.137, SMAPI 3.3.2.0",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137.zip",
|
||||
"hash": "bd16e8e4cb52d636e24c6a2d2309b66a60e492d2b97c1b8f6a519c04ac42ebdc"
|
||||
"description": "SMAPI兼容包, 适用版本1.4.4.128 - 1.4.5.137, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_137_2.zip",
|
||||
"hash": "3607a1f0647d49963a9803cc0445bba23a19b3c92c3b747eb12569fdb5d9b95e"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI三星商店兼容包",
|
||||
"assetPath": "compat/samsung_138/",
|
||||
"description": "SMAPI三星商店兼容包, 适用版本1.4.4.138至今, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_21.zip",
|
||||
"hash": "a77e8d35e0d1118bd03acda038ba00c4e13adc5eb73ebf8c200dfacdf85ef0a1"
|
||||
"description": "SMAPI三星商店兼容包, 适用版本1.4.4.138至今, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_samsung_138_22.zip",
|
||||
"hash": "e17f369ed84b2d30e6f552d27d7a06c7026a5ddf1de4552c86f31bbff6088ed9"
|
||||
},
|
||||
{
|
||||
"type": "COMPAT",
|
||||
"name": "SMAPI亚马逊商店兼容包",
|
||||
"assetPath": "compat/amazon_138/",
|
||||
"description": "SMAPI亚马逊商店兼容包, 适用版本1.4.4.138至今, SMAPI 3.7.3.2",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_11.zip",
|
||||
"hash": "f792ea943d2892b9c6c1116eec05916577f5f0385730a61a3d80d5d5b65b6c7d"
|
||||
"description": "SMAPI亚马逊商店兼容包, 适用版本1.4.4.138至今, SMAPI 3.7.3.3",
|
||||
"url": "http://zaneyork.cn/dl/compat/smapi_amazon_138_12.zip",
|
||||
"hash": "a7746738ee384d2142c2d3075a400d93f95c84bae2d56ce0e84894f24307d7a2"
|
||||
},
|
||||
{
|
||||
"type": "LOCALE",
|
||||
|
|
|
@ -11,8 +11,6 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import com.hjq.language.LanguagesManager;
|
||||
import com.lmntrx.android.library.livin.missme.ProgressDialog;
|
||||
import com.lzy.okgo.OkGo;
|
||||
|
@ -23,6 +21,7 @@ import com.microsoft.appcenter.crashes.Crashes;
|
|||
import com.zane.smapiinstaller.constant.AppConfigKeyConstants;
|
||||
import com.zane.smapiinstaller.constant.Constants;
|
||||
import com.zane.smapiinstaller.constant.DialogAction;
|
||||
import com.zane.smapiinstaller.databinding.ActivityMainBinding;
|
||||
import com.zane.smapiinstaller.dto.AppUpdateCheckResultDto;
|
||||
import com.zane.smapiinstaller.entity.AppConfig;
|
||||
import com.zane.smapiinstaller.entity.FrameworkConfig;
|
||||
|
@ -45,17 +44,12 @@ import java.util.Locale;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.navigation.ui.AppBarConfiguration;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
|
@ -64,21 +58,10 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
private AppBarConfiguration mAppBarConfiguration;
|
||||
|
||||
@BindView(R.id.launch)
|
||||
public FloatingActionButton buttonLaunch;
|
||||
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
|
||||
@BindView(R.id.drawer_layout)
|
||||
DrawerLayout drawer;
|
||||
|
||||
@BindView(R.id.nav_view)
|
||||
NavigationView navigationView;
|
||||
|
||||
private int currentFragment = R.id.nav_main;
|
||||
|
||||
public static MainActivity instance;
|
||||
private ActivityMainBinding binding;
|
||||
|
||||
private void requestPermissions() {
|
||||
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
|
@ -109,13 +92,13 @@ public class MainActivity extends AppCompatActivity {
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
instance = this;
|
||||
setContentView(R.layout.activity_main);
|
||||
ButterKnife.bind(this);
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
AppConfig appConfig = ConfigUtils.getConfig((MainApplication) this.getApplication(), AppConfigKeyConstants.PRIVACY_POLICY_CONFIRM, false);
|
||||
if (Boolean.parseBoolean(appConfig.getValue())) {
|
||||
requestPermissions();
|
||||
} else {
|
||||
CommonLogic.showPrivacyPolicy(toolbar, (dialog, action) -> {
|
||||
CommonLogic.showPrivacyPolicy(binding.appBarMain.toolbar, (dialog, action) -> {
|
||||
if (action == DialogAction.POSITIVE) {
|
||||
appConfig.setValue(String.valueOf(true));
|
||||
ConfigUtils.saveConfig((MainApplication) this.getApplication(), appConfig);
|
||||
|
@ -125,31 +108,32 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
});
|
||||
}
|
||||
binding.appBarMain.launch.setOnClickListener(v -> launchButtonClick());
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
AppCenter.start(getApplication(), Constants.APP_CENTER_SECRET, Analytics.class, Crashes.class);
|
||||
setSupportActionBar(toolbar);
|
||||
setSupportActionBar(binding.appBarMain.toolbar);
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
mAppBarConfiguration = new AppBarConfiguration.Builder(
|
||||
R.id.nav_main, R.id.nav_config, R.id.nav_help, R.id.nav_download, R.id.nav_about)
|
||||
.setOpenableLayout(drawer)
|
||||
.setOpenableLayout(binding.drawerLayout)
|
||||
.build();
|
||||
final NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
|
||||
NavigationUI.setupWithNavController(navigationView, navController);
|
||||
NavigationUI.setupWithNavController(binding.navView, navController);
|
||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
||||
currentFragment = destination.getId();
|
||||
this.invalidateOptionsMenu();
|
||||
switch (currentFragment){
|
||||
switch (currentFragment) {
|
||||
case R.id.nav_about:
|
||||
case R.id.nav_help:
|
||||
case R.id.config_edit_fragment:
|
||||
buttonLaunch.setVisibility(View.INVISIBLE);
|
||||
binding.appBarMain.launch.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
default:
|
||||
buttonLaunch.setVisibility(View.VISIBLE);
|
||||
binding.appBarMain.launch.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
AppConfig appConfig = ConfigUtils.getConfig((MainApplication) this.getApplication(), AppConfigKeyConstants.IGNORE_UPDATE_VERSION_CODE, Constants.PATCHED_APP_NAME);
|
||||
|
@ -168,7 +152,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
if (StringUtils.equals(appConfig.getValue(), String.valueOf(dto.getVersionCode()))) {
|
||||
return;
|
||||
}
|
||||
DialogUtils.showConfirmDialog(toolbar, R.string.settings_check_for_updates,
|
||||
DialogUtils.showConfirmDialog(binding.appBarMain.toolbar, R.string.settings_check_for_updates,
|
||||
MainActivity.this.getString(R.string.app_update_detected, dto.getVersionName()), (dialog, which) -> {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
CommonLogic.openUrl(MainActivity.this, Constants.RELEASE_URL);
|
||||
|
@ -181,9 +165,8 @@ public class MainActivity extends AppCompatActivity {
|
|||
});
|
||||
}
|
||||
|
||||
@OnClick(R.id.launch)
|
||||
void launchButtonClick() {
|
||||
new GameLauncher(navigationView).launch();
|
||||
new GameLauncher(binding.navView).launch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -199,10 +182,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
FrameworkConfig config = manager.getConfig();
|
||||
menu.findItem(R.id.settings_verbose_logging).setChecked(config.isVerboseLogging());
|
||||
menu.findItem(R.id.settings_check_for_updates).setChecked(config.isCheckForUpdates());
|
||||
if(currentFragment != R.id.nav_config) {
|
||||
if (currentFragment != R.id.nav_config) {
|
||||
menu.findItem(R.id.toolbar_update_check).setVisible(false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
menu.findItem(R.id.toolbar_update_check).setVisible(true);
|
||||
}
|
||||
menu.findItem(R.id.settings_developer_mode).setChecked(config.isDeveloperMode());
|
||||
|
@ -241,7 +223,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
config.setRewriteMissing(item.isChecked());
|
||||
break;
|
||||
case R.id.settings_set_app_name:
|
||||
DialogUtils.showInputDialog(toolbar, R.string.input, R.string.settings_set_app_name, Constants.PATCHED_APP_NAME, Constants.PATCHED_APP_NAME, true, (dialog, input) -> {
|
||||
DialogUtils.showInputDialog(binding.appBarMain.toolbar, R.string.input, R.string.settings_set_app_name, Constants.PATCHED_APP_NAME, Constants.PATCHED_APP_NAME, true, (dialog, input) -> {
|
||||
String appName = input.toString();
|
||||
AppConfig appConfig = ConfigUtils.getConfig((MainApplication) getApplication(), AppConfigKeyConstants.IGNORE_UPDATE_VERSION_CODE, appName);
|
||||
appConfig.setValue(appName);
|
||||
|
@ -250,7 +232,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
});
|
||||
return true;
|
||||
case R.id.settings_set_mod_path:
|
||||
DialogUtils.showInputDialog(toolbar, R.string.input, R.string.input_mods_path, Constants.MOD_PATH, Constants.MOD_PATH, (dialog, input) -> {
|
||||
DialogUtils.showInputDialog(binding.appBarMain.toolbar, R.string.input, R.string.input_mods_path, Constants.MOD_PATH, Constants.MOD_PATH, (dialog, input) -> {
|
||||
if (StringUtils.isNoneBlank(input)) {
|
||||
String pathString = input.toString();
|
||||
File file = new File(Environment.getExternalStorageDirectory(), pathString);
|
||||
|
@ -259,7 +241,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
config.setModsPath(pathString);
|
||||
manager.flushConfig();
|
||||
} else {
|
||||
DialogUtils.showAlertDialog(drawer, R.string.error, R.string.error_illegal_path);
|
||||
DialogUtils.showAlertDialog(binding.drawerLayout, R.string.error, R.string.error_illegal_path);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -303,7 +285,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
MainApplication application = (MainApplication) this.getApplication();
|
||||
AppConfig activeTranslator = ConfigUtils.getConfig(application, AppConfigKeyConstants.ACTIVE_TRANSLATOR, TranslateUtil.NONE);
|
||||
int index = getTranslateServiceIndex(activeTranslator);
|
||||
DialogUtils.showSingleChoiceDialog(toolbar, R.string.settings_translation_service, R.array.translators, index, (dialog, position) -> {
|
||||
DialogUtils.showSingleChoiceDialog(binding.appBarMain.toolbar, R.string.settings_translation_service, R.array.translators, index, (dialog, position) -> {
|
||||
switch (position) {
|
||||
case 0:
|
||||
activeTranslator.setValue(TranslateUtil.NONE);
|
||||
|
@ -323,7 +305,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void selectLanguageLogic() {
|
||||
DialogUtils.showListItemsDialog(toolbar, R.string.settings_set_language, R.array.languages, (dialog, position) -> {
|
||||
DialogUtils.showListItemsDialog(binding.appBarMain.toolbar, R.string.settings_set_language, R.array.languages, (dialog, position) -> {
|
||||
boolean restart;
|
||||
switch (position) {
|
||||
case 0:
|
||||
|
@ -369,7 +351,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void checkModUpdateLogic() {
|
||||
ModAssetsManager modAssetsManager = new ModAssetsManager(toolbar);
|
||||
ModAssetsManager modAssetsManager = new ModAssetsManager(binding.appBarMain.toolbar);
|
||||
modAssetsManager.checkModUpdate((list) -> {
|
||||
if (list.isEmpty()) {
|
||||
CommonLogic.runOnUiThread(this, (activity) -> Toast.makeText(activity, R.string.no_update_text, Toast.LENGTH_SHORT).show());
|
||||
|
@ -418,7 +400,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
public void setFloatingBarVisibility(boolean value) {
|
||||
buttonLaunch.setVisibility(value ? View.VISIBLE: View.INVISIBLE);
|
||||
binding.appBarMain.launch.setVisibility(value ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ public class Constants {
|
|||
/**
|
||||
* SMAPI版本
|
||||
*/
|
||||
public static final String SMAPI_VERSION = "3.7.2";
|
||||
public static final String SMAPI_VERSION = "3.7.3.3";
|
||||
|
||||
/**
|
||||
* 应用名称
|
||||
|
|
|
@ -6,6 +6,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
public class ActivityResultHandler {
|
||||
public static int REQUEST_CODE_APP_INSTALL = 1001;
|
||||
|
||||
|
|
|
@ -33,7 +33,9 @@ import com.zane.smapiinstaller.utils.ZipUtils;
|
|||
|
||||
import net.fornwall.apksigner.KeyStoreFileManager;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -52,6 +54,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import java.util.zip.Deflater;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -166,7 +169,7 @@ public class ApkPatcher {
|
|||
return patch(apkPath, false);
|
||||
}
|
||||
|
||||
public boolean patch(String apkPath, boolean advanced) {
|
||||
public boolean patch(String apkPath, boolean isAdvanced) {
|
||||
if (apkPath == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -191,38 +194,9 @@ public class ApkPatcher {
|
|||
ApkFilesManifest apkFilesManifest = apkFilesManifests.get(0);
|
||||
List<ManifestEntry> manifestEntries = apkFilesManifest.getManifestEntries();
|
||||
errorMessage.set(null);
|
||||
List<ZipUtils.ZipEntrySource> entries = manifestEntries.stream().map(entry -> {
|
||||
if (entry.isAdvanced() && !advanced) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes;
|
||||
if (entry.isExternal()) {
|
||||
bytes = FileUtils.getAssetBytes(context, apkFilesManifest.getBasePath() + entry.getAssetPath());
|
||||
} else {
|
||||
bytes = FileUtils.getAssetBytes(context, entry.getAssetPath());
|
||||
}
|
||||
if (StringUtils.isNoneBlank(entry.getPatchCrc())) {
|
||||
byte[] originBytes = ZipUtil.unpackEntry(file, entry.getTargetPath());
|
||||
if (originBytes != null) {
|
||||
String crc = Integer.toHexString(Hashing.crc32().hashBytes(originBytes).hashCode());
|
||||
if (StringUtils.equals(crc, entry.getPatchCrc())) {
|
||||
bytes = FileUtils.patchFile(originBytes, bytes);
|
||||
if (bytes == null) {
|
||||
String errorMsg = context.getString(R.string.error_patch_crc_incorrect, entry.getTargetPath(), crc);
|
||||
errorMessage.set(StringUtils.stripToEmpty(errorMessage.get()) + "\n" + errorMsg);
|
||||
return null;
|
||||
}
|
||||
} else if (StringUtils.equals(crc, entry.getPatchedCrc())) {
|
||||
bytes = originBytes;
|
||||
} else {
|
||||
String errorMsg = context.getString(R.string.error_patch_crc_incorrect, entry.getTargetPath(), crc);
|
||||
errorMessage.set(StringUtils.stripToEmpty(errorMessage.get()) + "\n" + errorMsg);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ZipUtils.ZipEntrySource(entry.getTargetPath(), bytes, entry.getCompression());
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
List<ZipUtils.ZipEntrySource> entries = manifestEntries.stream()
|
||||
.map(entry -> processfileentry(file, apkFilesManifest, entry, isAdvanced))
|
||||
.filter(Objects::nonNull).collect(Collectors.toList());
|
||||
if (errorMessage.get() != null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -248,6 +222,23 @@ public class ApkPatcher {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ZipUtils.ZipEntrySource processfileentry(File file, ApkFilesManifest apkFilesManifest, ManifestEntry entry, boolean isAdvanced) {
|
||||
if (entry.isAdvanced() && !isAdvanced) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes;
|
||||
if (entry.isExternal()) {
|
||||
bytes = FileUtils.getAssetBytes(context, apkFilesManifest.getBasePath() + entry.getAssetPath());
|
||||
} else {
|
||||
bytes = FileUtils.getAssetBytes(context, entry.getAssetPath());
|
||||
}
|
||||
if (StringUtils.isNoneBlank(entry.getPatchCrc())) {
|
||||
throw new NotImplementedException("bs patch mode is not supported anymore.");
|
||||
}
|
||||
return new ZipUtils.ZipEntrySource(entry.getTargetPath(), bytes, entry.getCompression());
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描全部兼容包,寻找匹配的版本,修改AndroidManifest.xml文件
|
||||
*
|
||||
|
@ -279,10 +270,9 @@ public class ApkPatcher {
|
|||
break;
|
||||
case "label":
|
||||
if (strObj.contains(ManifestPatchConstants.APP_NAME)) {
|
||||
if(StringUtils.isBlank(Constants.PATCHED_APP_NAME)) {
|
||||
if (StringUtils.isBlank(Constants.PATCHED_APP_NAME)) {
|
||||
attr.obj = context.getString(R.string.smapi_game_name);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
attr.obj = Constants.PATCHED_APP_NAME;
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +402,7 @@ public class ApkPatcher {
|
|||
boolean haveInstallPermission = context.getPackageManager().canRequestPackageInstalls();
|
||||
if (!haveInstallPermission) {
|
||||
DialogUtils.showConfirmDialog(MainActivity.instance, R.string.confirm, R.string.request_unknown_source_permission, ((dialog, dialogAction) -> {
|
||||
if(dialogAction == DialogAction.POSITIVE) {
|
||||
if (dialogAction == DialogAction.POSITIVE) {
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
|
||||
ActivityResultHandler.registerListener(ActivityResultHandler.REQUEST_CODE_APP_INSTALL, (resultCode, data) -> this.install(apkPath));
|
||||
MainActivity.instance.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_APP_INSTALL);
|
||||
|
|
|
@ -8,51 +8,49 @@ import android.os.Bundle;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.microsoft.appcenter.crashes.Crashes;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.constant.Constants;
|
||||
import com.zane.smapiinstaller.databinding.FragmentAboutBinding;
|
||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||
import com.zane.smapiinstaller.utils.DialogUtils;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
public class AboutFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.img_heart)
|
||||
ImageView imgHeart;
|
||||
private FragmentAboutBinding binding;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_about, container, false);
|
||||
ButterKnife.bind(this, root);
|
||||
return root;
|
||||
binding = FragmentAboutBinding.inflate(inflater, container, false);
|
||||
binding.buttonRelease.setOnClickListener(v -> release());
|
||||
binding.buttonQqGroup1.setOnClickListener(v -> joinQQ());
|
||||
binding.buttonDonation.setOnClickListener(v -> donation());
|
||||
binding.buttonPrivacyPolicy.setOnClickListener(v -> privacyPolicy());
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_release)
|
||||
void release() {
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void release() {
|
||||
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, Constants.RELEASE_URL));
|
||||
}
|
||||
|
||||
// @OnClick(R.id.button_gplay)
|
||||
void gplay() {
|
||||
CommonLogic.openInPlayStore(this.getActivity());
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_qq_group_1)
|
||||
void joinQQ() {
|
||||
private void joinQQ() {
|
||||
String baseUrl = "mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D";
|
||||
DialogUtils.showListItemsDialog(imgHeart, R.string.button_qq_group_text, R.array.qq_group_list, (dialog, position) -> {
|
||||
switch (position){
|
||||
DialogUtils.showListItemsDialog(binding.imgHeart, R.string.button_qq_group_text, R.array.qq_group_list, (dialog, position) -> {
|
||||
switch (position) {
|
||||
case 0:
|
||||
CommonLogic.doOnNonNull(this.getContext(), (context) -> CommonLogic.openUrl(context, baseUrl + "AAflCLHiWw1haM1obu_f-CpGsETxXc6b"));
|
||||
break;
|
||||
|
@ -66,16 +64,14 @@ public class AboutFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_donation)
|
||||
void donation() {
|
||||
DialogUtils.showListItemsDialog(imgHeart, R.string.button_donation_text, R.array.donation_methods, (dialog, position) ->
|
||||
CommonLogic.showAnimation(imgHeart, R.anim.heart_beat, (animation) ->
|
||||
DialogUtils.showListItemsDialog(binding.imgHeart, R.string.button_donation_text, R.array.donation_methods, (dialog, position) ->
|
||||
CommonLogic.showAnimation(binding.imgHeart, R.anim.heart_beat, (animation) ->
|
||||
CommonLogic.doOnNonNull(this.getActivity(), (activity) -> listSelectLogic(activity, position))));
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_privacy_policy)
|
||||
void privacyPolicy() {
|
||||
CommonLogic.showPrivacyPolicy(imgHeart, (dialog, dialogAction) -> {
|
||||
private void privacyPolicy() {
|
||||
CommonLogic.showPrivacyPolicy(binding.imgHeart, (dialog, dialogAction) -> {
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,12 @@ import android.os.Bundle;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.zane.smapiinstaller.BuildConfig;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.constant.Constants;
|
||||
import com.zane.smapiinstaller.constant.DialogAction;
|
||||
import com.zane.smapiinstaller.databinding.FragmentConfigEditBinding;
|
||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||
import com.zane.smapiinstaller.utils.DialogUtils;
|
||||
import com.zane.smapiinstaller.utils.FileUtils;
|
||||
|
@ -27,50 +26,40 @@ import androidx.annotation.NonNull;
|
|||
import androidx.core.content.FileProvider;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.Navigation;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
public class ConfigEditFragment extends Fragment {
|
||||
@BindView(R.id.edit_text_config_edit)
|
||||
EditText editText;
|
||||
private Boolean editable;
|
||||
private String configPath;
|
||||
@BindView(R.id.button_config_save)
|
||||
Button buttonConfigSave;
|
||||
@BindView(R.id.button_config_cancel)
|
||||
Button buttonConfigCancel;
|
||||
@BindView(R.id.button_log_parser)
|
||||
Button buttonLogParser;
|
||||
|
||||
private FragmentConfigEditBinding binding;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_config_edit, container, false);
|
||||
ButterKnife.bind(this, root);
|
||||
binding = FragmentConfigEditBinding.inflate(inflater, container, false);
|
||||
CommonLogic.doOnNonNull(this.getArguments(), arguments -> {
|
||||
ConfigEditFragmentArgs args = ConfigEditFragmentArgs.fromBundle(arguments);
|
||||
editable = args.getEditable();
|
||||
if (!editable) {
|
||||
editText.setKeyListener(null);
|
||||
buttonConfigSave.setVisibility(View.INVISIBLE);
|
||||
buttonConfigCancel.setVisibility(View.INVISIBLE);
|
||||
buttonLogParser.setVisibility(View.VISIBLE);
|
||||
binding.editTextConfigEdit.setKeyListener(null);
|
||||
binding.buttonConfigSave.setVisibility(View.INVISIBLE);
|
||||
binding.buttonConfigCancel.setVisibility(View.INVISIBLE);
|
||||
binding.buttonLogParser.setVisibility(View.VISIBLE);
|
||||
}
|
||||
configPath = args.getConfigPath();
|
||||
File file = new File(configPath);
|
||||
if (file.exists() && file.length() < Constants.TEXT_FILE_OPEN_SIZE_LIMIT) {
|
||||
String fileText = FileUtils.getFileText(file);
|
||||
if (fileText != null) {
|
||||
editText.setText(fileText);
|
||||
binding.editTextConfigEdit.setText(fileText);
|
||||
}
|
||||
} else {
|
||||
editText.setText("");
|
||||
editText.setKeyListener(null);
|
||||
DialogUtils.showConfirmDialog(root, R.string.error, this.getString(R.string.text_too_large), R.string.open_with, R.string.cancel, ((dialog, which) -> {
|
||||
binding.editTextConfigEdit.setText("");
|
||||
binding.editTextConfigEdit.setKeyListener(null);
|
||||
DialogUtils.showConfirmDialog(binding.getRoot(), R.string.error, this.getString(R.string.text_too_large), R.string.open_with, R.string.cancel, ((dialog, which) -> {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
Intent intent = new Intent("android.intent.action.VIEW");
|
||||
intent.addCategory("android.intent.category.DEFAULT");
|
||||
|
@ -90,16 +79,23 @@ public class ConfigEditFragment extends Fragment {
|
|||
}));
|
||||
}
|
||||
});
|
||||
return root;
|
||||
binding.buttonConfigCancel.setOnClickListener(v -> onConfigCancel());
|
||||
binding.buttonConfigSave.setOnClickListener(v -> onConfigSave());
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_config_save)
|
||||
void onConfigSave() {
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void onConfigSave() {
|
||||
try {
|
||||
JsonUtil.checkJson(editText.getText().toString());
|
||||
JsonUtil.checkJson(binding.editTextConfigEdit.getText().toString());
|
||||
FileOutputStream outputStream = new FileOutputStream(configPath);
|
||||
try (OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream)) {
|
||||
outputStreamWriter.write(editText.getText().toString());
|
||||
outputStreamWriter.write(binding.editTextConfigEdit.getText().toString());
|
||||
outputStreamWriter.flush();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -107,13 +103,11 @@ public class ConfigEditFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_config_cancel)
|
||||
void onConfigCancel() {
|
||||
private void onConfigCancel() {
|
||||
CommonLogic.doOnNonNull(getView(), view -> Navigation.findNavController(view).popBackStack());
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_log_parser)
|
||||
void onLogParser() {
|
||||
private void onLogParser() {
|
||||
CommonLogic.doOnNonNull(getContext(), context -> CommonLogic.openUrl(context, "https://smapi.io/log"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.databinding.FragmentConfigBinding;
|
||||
import com.zane.smapiinstaller.utils.DialogUtils;
|
||||
import com.zane.smapiinstaller.utils.function.TextChangedWatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -14,44 +16,40 @@ import androidx.annotation.NonNull;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnTextChanged;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
public class ConfigFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.view_mod_list)
|
||||
RecyclerView recyclerView;
|
||||
private ConfigViewModel configViewModel;
|
||||
|
||||
private FragmentConfigBinding binding;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_config, container, false);
|
||||
ButterKnife.bind(this, root);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
|
||||
configViewModel = new ConfigViewModel(root);
|
||||
binding = FragmentConfigBinding.inflate(inflater, container, false);
|
||||
binding.viewModList.setLayoutManager(new LinearLayoutManager(this.getContext()));
|
||||
configViewModel = new ConfigViewModel(binding.getRoot());
|
||||
ModManifestAdapter modManifestAdapter = new ModManifestAdapter(configViewModel, new ArrayList<>(configViewModel.getModList()));
|
||||
recyclerView.setAdapter(modManifestAdapter);
|
||||
binding.viewModList.setAdapter(modManifestAdapter);
|
||||
configViewModel.registerOnChangeListener((list) -> {
|
||||
modManifestAdapter.setList(new ArrayList<>(list));
|
||||
return false;
|
||||
});
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
|
||||
return root;
|
||||
binding.viewModList.addItemDecoration(new DividerItemDecoration(binding.viewModList.getContext(), DividerItemDecoration.VERTICAL));
|
||||
binding.buttonSearch.addTextChangedListener((TextChangedWatcher) (s, start, before, count) -> configViewModel.filter(s));
|
||||
binding.buttonSortBy.setOnClickListener(v -> onSortByClick());
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@OnTextChanged(R.id.button_search)
|
||||
void onSearchMod(CharSequence text) {
|
||||
configViewModel.filter(text);
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_sort_by)
|
||||
void onSortByClick() {
|
||||
int index = 0;
|
||||
switch (configViewModel.getSortBy()) {
|
||||
|
@ -69,7 +67,7 @@ public class ConfigFragment extends Fragment {
|
|||
break;
|
||||
default:
|
||||
}
|
||||
DialogUtils.showSingleChoiceDialog(recyclerView, R.string.sort_by, R.array.mod_list_sort_by, index, (dialog, position) -> {
|
||||
DialogUtils.showSingleChoiceDialog(binding.viewModList, R.string.sort_by, R.array.mod_list_sort_by, index, (dialog, position) -> {
|
||||
switch (position) {
|
||||
case 0:
|
||||
configViewModel.switchSortBy("Name asc");
|
||||
|
|
|
@ -4,13 +4,12 @@ import android.graphics.Paint;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.zane.smapiinstaller.MobileNavigationDirections;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.constant.Constants;
|
||||
import com.zane.smapiinstaller.constant.DialogAction;
|
||||
import com.zane.smapiinstaller.databinding.ModListItemBinding;
|
||||
import com.zane.smapiinstaller.entity.ModManifestEntry;
|
||||
import com.zane.smapiinstaller.utils.DialogUtils;
|
||||
import com.zane.smapiinstaller.utils.FileUtils;
|
||||
|
@ -21,15 +20,12 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
|
@ -38,23 +34,23 @@ public class ModManifestAdapter extends RecyclerView.Adapter<ModManifestAdapter.
|
|||
private ConfigViewModel model;
|
||||
private List<ModManifestEntry> modList;
|
||||
|
||||
public ModManifestAdapter(ConfigViewModel model, List<ModManifestEntry> modList){
|
||||
this.model=model;
|
||||
public ModManifestAdapter(ConfigViewModel model, List<ModManifestEntry> modList) {
|
||||
this.model = model;
|
||||
this.modList = modList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.mod_list_item,parent, false);
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.mod_list_item, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
ModManifestEntry mod = modList.get(position);
|
||||
holder.modName.setText(mod.getName());
|
||||
holder.modDescription.setText(StringUtils.firstNonBlank(mod.getTranslatedDescription(), mod.getDescription()));
|
||||
holder.binding.textViewModName.setText(mod.getName());
|
||||
holder.binding.textViewModDescription.setText(StringUtils.firstNonBlank(mod.getTranslatedDescription(), mod.getDescription()));
|
||||
holder.setModPath(mod.getAssetPath());
|
||||
}
|
||||
|
||||
|
@ -68,37 +64,35 @@ public class ModManifestAdapter extends RecyclerView.Adapter<ModManifestAdapter.
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder{
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private ModListItemBinding binding;
|
||||
private String modPath;
|
||||
|
||||
void setModPath(String modPath) {
|
||||
this.modPath = modPath;
|
||||
File file = new File(modPath, "config.json");
|
||||
if(!file.exists()) {
|
||||
configModButton.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
else {
|
||||
configModButton.setVisibility(View.VISIBLE);
|
||||
if (!file.exists()) {
|
||||
binding.buttonConfigMod.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
binding.buttonConfigMod.setVisibility(View.VISIBLE);
|
||||
}
|
||||
setStrike();
|
||||
}
|
||||
@BindView(R.id.button_config_mod)
|
||||
Button configModButton;
|
||||
@BindView(R.id.text_view_mod_name)
|
||||
TextView modName;
|
||||
@BindView(R.id.text_view_mod_description)
|
||||
TextView modDescription;
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
|
||||
ViewHolder(@NonNull View view) {
|
||||
super(view);
|
||||
binding = ModListItemBinding.bind(view);
|
||||
binding.buttonRemoveMod.setOnClickListener(v -> removeMod());
|
||||
binding.buttonDisableMod.setOnClickListener(v -> disableMod());
|
||||
binding.buttonConfigMod.setOnClickListener(v -> configMod());
|
||||
}
|
||||
|
||||
private void setStrike() {
|
||||
File file = new File(modPath);
|
||||
if(StringUtils.startsWith(file.getName(), Constants.HIDDEN_FILE_PREFIX)) {
|
||||
modName.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
}
|
||||
else {
|
||||
modName.getPaint().setFlags(modName.getPaint().getFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
|
||||
if (StringUtils.startsWith(file.getName(), Constants.HIDDEN_FILE_PREFIX)) {
|
||||
binding.textViewModName.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
|
||||
} else {
|
||||
binding.textViewModName.getPaint().setFlags(binding.textViewModName.getPaint().getFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,8 +107,8 @@ public class ModManifestAdapter extends RecyclerView.Adapter<ModManifestAdapter.
|
|||
return deletedId;
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_remove_mod) void removeMod() {
|
||||
DialogUtils.showConfirmDialog(itemView, R.string.confirm, R.string.confirm_delete_content, (dialog, which)->{
|
||||
void removeMod() {
|
||||
DialogUtils.showConfirmDialog(itemView, R.string.confirm, R.string.confirm_delete_content, (dialog, which) -> {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
File file = new File(modPath);
|
||||
if (file.exists()) {
|
||||
|
@ -132,16 +126,16 @@ public class ModManifestAdapter extends RecyclerView.Adapter<ModManifestAdapter.
|
|||
}
|
||||
});
|
||||
}
|
||||
@OnClick(R.id.button_disable_mod) void disableMod() {
|
||||
|
||||
void disableMod() {
|
||||
File file = new File(modPath);
|
||||
if(file.exists() && file.isDirectory()) {
|
||||
if(StringUtils.startsWith(file.getName(), Constants.HIDDEN_FILE_PREFIX)) {
|
||||
if (file.exists() && file.isDirectory()) {
|
||||
if (StringUtils.startsWith(file.getName(), Constants.HIDDEN_FILE_PREFIX)) {
|
||||
File newFile = new File(file.getParent(), StringUtils.stripStart(file.getName(), "."));
|
||||
moveMod(file, newFile);
|
||||
}
|
||||
else {
|
||||
DialogUtils.showConfirmDialog(itemView, R.string.confirm, R.string.confirm_disable_mod, (dialog, which)-> {
|
||||
if(which == DialogAction.POSITIVE) {
|
||||
} else {
|
||||
DialogUtils.showConfirmDialog(itemView, R.string.confirm, R.string.confirm_disable_mod, (dialog, which) -> {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
File newFile = new File(file.getParent(), "." + file.getName());
|
||||
moveMod(file, newFile);
|
||||
}
|
||||
|
@ -172,9 +166,9 @@ public class ModManifestAdapter extends RecyclerView.Adapter<ModManifestAdapter.
|
|||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_config_mod) void configMod() {
|
||||
void configMod() {
|
||||
File file = new File(modPath, "config.json");
|
||||
if(file.exists()) {
|
||||
if (file.exists()) {
|
||||
NavController controller = Navigation.findNavController(itemView);
|
||||
MobileNavigationDirections.ActionNavAnyToConfigEditFragment action = ConfigFragmentDirections.actionNavAnyToConfigEditFragment(file.getAbsolutePath());
|
||||
controller.navigate(action);
|
||||
|
|
|
@ -4,8 +4,6 @@ import android.content.Context;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.lmntrx.android.library.livin.missme.ProgressDialog;
|
||||
import com.lzy.okgo.OkGo;
|
||||
|
@ -16,6 +14,7 @@ import com.microsoft.appcenter.crashes.Crashes;
|
|||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.constant.DialogAction;
|
||||
import com.zane.smapiinstaller.constant.DownloadableContentTypeConstants;
|
||||
import com.zane.smapiinstaller.databinding.DownloadContentItemBinding;
|
||||
import com.zane.smapiinstaller.entity.DownloadableContent;
|
||||
import com.zane.smapiinstaller.entity.ModManifestEntry;
|
||||
import com.zane.smapiinstaller.logic.ModAssetsManager;
|
||||
|
@ -33,9 +32,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* {@link RecyclerView.Adapter} that can display a {@link DownloadableContent}
|
||||
|
@ -74,50 +70,43 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
|
|||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.text_item_type)
|
||||
TextView typeTextView;
|
||||
@BindView(R.id.text_item_name)
|
||||
TextView nameTextView;
|
||||
@BindView(R.id.text_item_description)
|
||||
TextView descriptionTextView;
|
||||
@BindView(R.id.button_remove_content)
|
||||
Button buttonRemove;
|
||||
@BindView(R.id.button_download_content)
|
||||
Button buttonDownload;
|
||||
private DownloadContentItemBinding binding;
|
||||
|
||||
private final AtomicBoolean downloading = new AtomicBoolean(false);
|
||||
|
||||
public DownloadableContent downloadableContent;
|
||||
|
||||
public void setDownloadableContent(DownloadableContent downloadableContent) {
|
||||
this.downloadableContent = downloadableContent;
|
||||
typeTextView.setText(downloadableContent.getType());
|
||||
nameTextView.setText(downloadableContent.getName());
|
||||
descriptionTextView.setText(downloadableContent.getDescription());
|
||||
binding.textItemType.setText(downloadableContent.getType());
|
||||
binding.textItemName.setText(downloadableContent.getName());
|
||||
binding.textItemDescription.setText(downloadableContent.getDescription());
|
||||
if (StringUtils.isNoneBlank(downloadableContent.getAssetPath())) {
|
||||
File contentFile = new File(itemView.getContext().getFilesDir(), downloadableContent.getAssetPath());
|
||||
if (contentFile.exists()) {
|
||||
Context context = itemView.getContext();
|
||||
File file = new File(context.getCacheDir(), downloadableContent.getName() + ".zip");
|
||||
if (!file.exists() || !StringUtils.equalsIgnoreCase(FileUtils.getFileHash(file), downloadableContent.getHash())) {
|
||||
buttonRemove.setVisibility(View.VISIBLE);
|
||||
buttonDownload.setVisibility(View.VISIBLE);
|
||||
binding.buttonRemoveContent.setVisibility(View.VISIBLE);
|
||||
binding.buttonDownloadContent.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
buttonRemove.setVisibility(View.VISIBLE);
|
||||
buttonDownload.setVisibility(View.INVISIBLE);
|
||||
binding.buttonRemoveContent.setVisibility(View.VISIBLE);
|
||||
binding.buttonDownloadContent.setVisibility(View.INVISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
buttonRemove.setVisibility(View.INVISIBLE);
|
||||
buttonDownload.setVisibility(View.VISIBLE);
|
||||
binding.buttonRemoveContent.setVisibility(View.INVISIBLE);
|
||||
binding.buttonDownloadContent.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, itemView);
|
||||
binding = DownloadContentItemBinding.bind(view);
|
||||
binding.buttonRemoveContent.setOnClickListener(v -> removeContent());
|
||||
binding.buttonDownloadContent.setOnClickListener(v -> downloadContent());
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_remove_content)
|
||||
void removeContent() {
|
||||
if (StringUtils.isNoneBlank(downloadableContent.getAssetPath())) {
|
||||
File contentFile = new File(itemView.getContext().getFilesDir(), downloadableContent.getAssetPath());
|
||||
|
@ -126,8 +115,8 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
|
|||
if (which == DialogAction.POSITIVE) {
|
||||
try {
|
||||
FileUtils.forceDelete(contentFile);
|
||||
buttonDownload.setVisibility(View.VISIBLE);
|
||||
buttonRemove.setVisibility(View.INVISIBLE);
|
||||
binding.buttonDownloadContent.setVisibility(View.VISIBLE);
|
||||
binding.buttonRemoveContent.setVisibility(View.INVISIBLE);
|
||||
} catch (IOException e) {
|
||||
DialogUtils.showAlertDialog(itemView, R.string.error, e.getLocalizedMessage());
|
||||
}
|
||||
|
@ -137,7 +126,6 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
|
|||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_download_content)
|
||||
void downloadContent() {
|
||||
Context context = itemView.getContext();
|
||||
ModManifestEntry modManifestEntry = null;
|
||||
|
@ -212,8 +200,8 @@ public class DownloadableContentAdapter extends RecyclerView.Adapter<Downloadabl
|
|||
ZipUtil.unpack(downloadedFile, new File(context.getFilesDir(), downloadableContent.getAssetPath()));
|
||||
}
|
||||
DialogUtils.showAlertDialog(itemView, R.string.info, R.string.download_unpack_success);
|
||||
buttonDownload.setVisibility(View.INVISIBLE);
|
||||
buttonRemove.setVisibility(View.VISIBLE);
|
||||
binding.buttonDownloadContent.setVisibility(View.INVISIBLE);
|
||||
binding.buttonRemoveContent.setVisibility(View.VISIBLE);
|
||||
} catch (Exception e) {
|
||||
DialogUtils.showAlertDialog(itemView, R.string.error, e.getLocalizedMessage());
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
|
||||
import com.zane.smapiinstaller.MobileNavigationDirections;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.constant.Constants;
|
||||
import com.zane.smapiinstaller.databinding.FragmentHelpBinding;
|
||||
import com.zane.smapiinstaller.entity.HelpItemList;
|
||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||
import com.zane.smapiinstaller.logic.UpdatableListManager;
|
||||
|
@ -21,46 +21,52 @@ import androidx.navigation.NavController;
|
|||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
public class HelpFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.view_help_list)
|
||||
RecyclerView recyclerView;
|
||||
private FragmentHelpBinding binding;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_help, container, false);
|
||||
ButterKnife.bind(this, root);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
|
||||
UpdatableListManager<HelpItemList> manager = new UpdatableListManager<>(root, "help_item_list.json", HelpItemList.class, Constants.HELP_LIST_UPDATE_URL);
|
||||
binding = FragmentHelpBinding.inflate(inflater, container, false);
|
||||
binding.viewHelpList.setLayoutManager(new LinearLayoutManager(this.getContext()));
|
||||
UpdatableListManager<HelpItemList> manager = new UpdatableListManager<>(binding.getRoot(), "help_item_list.json", HelpItemList.class, Constants.HELP_LIST_UPDATE_URL);
|
||||
HelpItemAdapter adapter = new HelpItemAdapter(manager.getList().getItems());
|
||||
recyclerView.setAdapter(adapter);
|
||||
binding.viewHelpList.setAdapter(adapter);
|
||||
manager.registerOnChangeListener((list) -> {
|
||||
adapter.setHelpItems(list.getItems());
|
||||
return false;
|
||||
});
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
|
||||
return root;
|
||||
binding.viewHelpList.addItemDecoration(new DividerItemDecoration(binding.viewHelpList.getContext(), DividerItemDecoration.VERTICAL));
|
||||
binding.buttonCompat.setOnClickListener(v -> compat());
|
||||
binding.buttonNexus.setOnClickListener(v -> nexus());
|
||||
binding.buttonLogs.setOnClickListener(v -> showLog());
|
||||
return binding.getRoot();
|
||||
}
|
||||
@OnClick(R.id.button_compat) void compat() {
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void compat() {
|
||||
CommonLogic.doOnNonNull(this.getContext(), context -> CommonLogic.openUrl(context, "https://smapi.io/mods"));
|
||||
}
|
||||
@OnClick(R.id.button_nexus) void nexus() {
|
||||
|
||||
private void nexus() {
|
||||
CommonLogic.doOnNonNull(this.getContext(), context -> CommonLogic.openUrl(context, "https://www.nexusmods.com/stardewvalley/mods/"));
|
||||
}
|
||||
@OnClick({R.id.button_logs}) void showLog() {
|
||||
|
||||
private void showLog() {
|
||||
CommonLogic.doOnNonNull(this.getView(), view -> {
|
||||
NavController controller = Navigation.findNavController(view);
|
||||
File logFile = new File(Environment.getExternalStorageDirectory(), Constants.LOG_PATH);
|
||||
if(logFile.exists()) {
|
||||
if (logFile.exists()) {
|
||||
MobileNavigationDirections.ActionNavAnyToConfigEditFragment action = HelpFragmentDirections.actionNavAnyToConfigEditFragment(logFile.getAbsolutePath());
|
||||
action.setEditable(false);
|
||||
controller.navigate(action);
|
||||
|
|
|
@ -5,17 +5,15 @@ import android.text.method.LinkMovementMethod;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.databinding.HelpListItemBinding;
|
||||
import com.zane.smapiinstaller.entity.HelpItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
|
@ -52,26 +50,21 @@ public class HelpItemAdapter extends RecyclerView.Adapter<HelpItemAdapter.ViewHo
|
|||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.text_item_title)
|
||||
TextView textTitle;
|
||||
@BindView(R.id.text_item_author)
|
||||
TextView textAuthor;
|
||||
@BindView(R.id.text_item_content)
|
||||
TextView textContent;
|
||||
private HelpListItemBinding binding;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, itemView);
|
||||
binding = HelpListItemBinding.bind(view);
|
||||
}
|
||||
void setHelpItem(HelpItem item) {
|
||||
textTitle.setText(item.getTitle());
|
||||
textAuthor.setText(item.getAuthor());
|
||||
binding.textItemTitle.setText(item.getTitle());
|
||||
binding.textItemAuthor.setText(item.getAuthor());
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
textContent.setText(Html.fromHtml(item.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||
binding.textItemContent.setText(Html.fromHtml(item.getContent(), Html.FROM_HTML_MODE_COMPACT));
|
||||
} else {
|
||||
textContent.setText(Html.fromHtml(item.getContent()));
|
||||
binding.textItemContent.setText(Html.fromHtml(item.getContent()));
|
||||
}
|
||||
textContent.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
binding.textItemContent.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,6 @@ import android.os.Environment;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.zane.smapiinstaller.MainApplication;
|
||||
|
@ -17,6 +14,7 @@ import com.zane.smapiinstaller.R;
|
|||
import com.zane.smapiinstaller.constant.AppConfigKeyConstants;
|
||||
import com.zane.smapiinstaller.constant.Constants;
|
||||
import com.zane.smapiinstaller.constant.DialogAction;
|
||||
import com.zane.smapiinstaller.databinding.FragmentInstallBinding;
|
||||
import com.zane.smapiinstaller.logic.ApkPatcher;
|
||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||
import com.zane.smapiinstaller.logic.ModAssetsManager;
|
||||
|
@ -35,9 +33,6 @@ import androidx.annotation.NonNull;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
|
@ -48,44 +43,42 @@ public class InstallFragment extends Fragment {
|
|||
|
||||
private Thread task;
|
||||
|
||||
private View root;
|
||||
|
||||
@BindView(R.id.button_install)
|
||||
Button installButton;
|
||||
|
||||
@BindView(R.id.text_latest_running)
|
||||
TextView textLatestRunning;
|
||||
|
||||
@BindView(R.id.layout_adv_install)
|
||||
LinearLayout layoutAdvInstall;
|
||||
private FragmentInstallBinding binding;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
root = inflater.inflate(R.layout.fragment_install, container, false);
|
||||
ButterKnife.bind(this, root);
|
||||
binding = FragmentInstallBinding.inflate(inflater, container, false);
|
||||
context = this.getActivity();
|
||||
if (Boolean.parseBoolean(ConfigUtils.getConfig((MainApplication) context.getApplication(), AppConfigKeyConstants.ADVANCED_MODE, "false").getValue())) {
|
||||
installButton.setVisibility(View.INVISIBLE);
|
||||
layoutAdvInstall.setVisibility(View.VISIBLE);
|
||||
binding.buttonInstall.setVisibility(View.INVISIBLE);
|
||||
binding.layoutAdvInstall.setVisibility(View.VISIBLE);
|
||||
}
|
||||
try {
|
||||
String firstLine = Files.asCharSource(new File(Environment.getExternalStorageDirectory(), Constants.LOG_PATH), StandardCharsets.UTF_8).readFirstLine();
|
||||
if (StringUtils.isNoneBlank(firstLine)) {
|
||||
String versionString = RegExUtils.removePattern(firstLine, "\\[.+\\]\\s+");
|
||||
versionString = RegExUtils.removePattern(versionString, "\\s+with.+");
|
||||
textLatestRunning.setText(context.getString(R.string.smapi_version_runing, versionString));
|
||||
textLatestRunning.setVisibility(View.VISIBLE);
|
||||
binding.textLatestRunning.setText(context.getString(R.string.smapi_version_runing, versionString));
|
||||
binding.textLatestRunning.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return root;
|
||||
binding.buttonInstall.setOnClickListener(v -> InstallFragment.this.install());
|
||||
binding.buttonAdvInitial.setOnClickListener(v -> InstallFragment.this.initialLogic());
|
||||
binding.buttonAdvInstall.setOnClickListener(v -> InstallFragment.this.installLogic(true));
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_install)
|
||||
void install() {
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void install() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
DialogUtils.showConfirmDialog(root, R.string.confirm, R.string.android_version_confirm, ((dialog, which) -> {
|
||||
DialogUtils.showConfirmDialog(binding.getRoot(), R.string.confirm, R.string.android_version_confirm, ((dialog, which) -> {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
installLogic(false);
|
||||
}
|
||||
|
@ -95,16 +88,6 @@ public class InstallFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_adv_initial)
|
||||
void advInitial() {
|
||||
initialLogic();
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_adv_install)
|
||||
void advInstall() {
|
||||
installLogic(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化逻辑
|
||||
*/
|
||||
|
@ -112,13 +95,13 @@ public class InstallFragment extends Fragment {
|
|||
if (task != null) {
|
||||
task.interrupt();
|
||||
}
|
||||
task = new Thread(() -> CommonLogic.showProgressDialog(root, context, (dialog)->{
|
||||
task = new Thread(() -> CommonLogic.showProgressDialog(binding.getRoot(), context, (dialog)->{
|
||||
ApkPatcher patcher = new ApkPatcher(context);
|
||||
patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(root, dialog, null, progress));
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.extracting_package, null);
|
||||
patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(binding.getRoot(), dialog, null, progress));
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.extracting_package, null);
|
||||
String path = patcher.extract(0);
|
||||
if (path == null) {
|
||||
DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.error_game_not_found)));
|
||||
DialogUtils.showAlertDialog(binding.getRoot(), R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.error_game_not_found)));
|
||||
}
|
||||
}));
|
||||
task.start();
|
||||
|
@ -131,48 +114,47 @@ public class InstallFragment extends Fragment {
|
|||
if (task != null) {
|
||||
task.interrupt();
|
||||
}
|
||||
task = new Thread(() -> CommonLogic.showProgressDialog(root, context, (dialog)-> {
|
||||
task = new Thread(() -> CommonLogic.showProgressDialog(binding.getRoot(), context, (dialog)-> {
|
||||
ApkPatcher patcher = new ApkPatcher(context);
|
||||
patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(root, dialog, null, progress));
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.extracting_package, null);
|
||||
patcher.registerProgressListener((progress) -> DialogUtils.setProgressDialogState(binding.getRoot(), dialog, null, progress));
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.extracting_package, null);
|
||||
String path = patcher.extract(isAdv ? 1 : -1);
|
||||
if (path == null) {
|
||||
DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.error_game_not_found)));
|
||||
DialogUtils.showAlertDialog(binding.getRoot(), R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.error_game_not_found)));
|
||||
return;
|
||||
}
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.unpacking_smapi_files, null);
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.unpacking_smapi_files, null);
|
||||
if (!CommonLogic.unpackSmapiFiles(context, path, false)) {
|
||||
DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_unpack_smapi_files)));
|
||||
DialogUtils.showAlertDialog(binding.getRoot(), R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_unpack_smapi_files)));
|
||||
return;
|
||||
}
|
||||
ModAssetsManager modAssetsManager = new ModAssetsManager(root);
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.unpacking_smapi_files, 6);
|
||||
ModAssetsManager modAssetsManager = new ModAssetsManager(binding.getRoot());
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.unpacking_smapi_files, 6);
|
||||
modAssetsManager.installDefaultMods();
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.patching_package, 8);
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.patching_package, 8);
|
||||
if (!patcher.patch(path, isAdv)) {
|
||||
int target = patcher.getSwitchAction().getAndSet(0);
|
||||
if (target == R.string.menu_download) {
|
||||
DialogUtils.showConfirmDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)), R.string.menu_download, R.string.cancel, (d, which) -> {
|
||||
DialogUtils.showConfirmDialog(binding.getRoot(), R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)), R.string.menu_download, R.string.cancel, (d, which) -> {
|
||||
if (which == DialogAction.POSITIVE) {
|
||||
NavController controller = Navigation.findNavController(installButton);
|
||||
NavController controller = Navigation.findNavController(binding.buttonInstall);
|
||||
controller.navigate(MainTabsFragmentDirections.actionNavMainToNavDownload());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)));
|
||||
DialogUtils.showAlertDialog(binding.getRoot(), R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_patch_game)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.signing_package, null);
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.signing_package, null);
|
||||
String signPath = patcher.sign(path);
|
||||
if (signPath == null) {
|
||||
DialogUtils.showAlertDialog(root, R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_sign_game)));
|
||||
DialogUtils.showAlertDialog(binding.getRoot(), R.string.error, StringUtils.firstNonBlank(patcher.getErrorMessage().get(), context.getString(R.string.failed_to_sign_game)));
|
||||
return;
|
||||
}
|
||||
DialogUtils.setProgressDialogState(root, dialog, R.string.installing_package, null);
|
||||
DialogUtils.setProgressDialogState(binding.getRoot(), dialog, R.string.installing_package, null);
|
||||
patcher.install(signPath);
|
||||
}));
|
||||
task.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,46 +5,45 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import com.zane.smapiinstaller.MainActivity;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.databinding.FragmentMainBinding;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
public class MainTabsFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.main_tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.main_pager)
|
||||
ViewPager2 viewPager;
|
||||
private FragmentMainBinding binding;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_main, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
binding = FragmentMainBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
MainTabPagerAdapter pagerAdapter = new MainTabPagerAdapter(this);
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
new TabLayoutMediator(tabLayout, viewPager,
|
||||
binding.mainPager.setAdapter(pagerAdapter);
|
||||
new TabLayoutMediator(binding.mainTabLayout, binding.mainPager,
|
||||
(tab, position) -> tab.setText(pagerAdapter.getTitle(position))
|
||||
).attach();
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
binding.mainPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
|
|
|
@ -3,11 +3,11 @@ package com.zane.smapiinstaller.ui.update;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.databinding.UpdatableModListItemBinding;
|
||||
import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto;
|
||||
import com.zane.smapiinstaller.entity.ModManifestEntry;
|
||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||
|
@ -15,13 +15,10 @@ import com.zane.smapiinstaller.logic.ModAssetsManager;
|
|||
import com.zane.smapiinstaller.utils.VersionUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@link RecyclerView.Adapter} that can display a {@link ModUpdateCheckResponseDto.UpdateInfo}
|
||||
|
@ -59,20 +56,17 @@ public class ModUpdateAdapter extends RecyclerView.Adapter<ModUpdateAdapter.View
|
|||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public ModUpdateCheckResponseDto updateInfo;
|
||||
@BindView(R.id.text_view_mod_name)
|
||||
TextView textModName;
|
||||
@BindView(R.id.text_view_mod_version)
|
||||
TextView textModVersion;
|
||||
private UpdatableModListItemBinding binding;
|
||||
|
||||
public void setUpdateInfo(ModUpdateCheckResponseDto updateInfo) {
|
||||
this.updateInfo = updateInfo;
|
||||
String id = updateInfo.getId();
|
||||
Optional<ModManifestEntry> mod = installedModMap.get(id).stream().sorted((a, b) -> VersionUtil.compareVersion(a.getVersion(), b.getVersion())).findFirst();
|
||||
Optional<ModManifestEntry> mod = installedModMap.get(id).stream().min((a, b) -> VersionUtil.compareVersion(a.getVersion(), b.getVersion()));
|
||||
if (mod.isPresent()) {
|
||||
ModManifestEntry modManifestEntry = mod.get();
|
||||
textModName.setText(modManifestEntry.getName());
|
||||
CommonLogic.doOnNonNull(CommonLogic.getActivityFromView(textModName),
|
||||
activity -> textModVersion.setText(
|
||||
binding.textViewModName.setText(modManifestEntry.getName());
|
||||
CommonLogic.doOnNonNull(CommonLogic.getActivityFromView(binding.textViewModName),
|
||||
activity -> binding.textViewModVersion.setText(
|
||||
activity.getString(R.string.mod_version_update_text, modManifestEntry.getVersion(), updateInfo.getSuggestedUpdate().getVersion())
|
||||
));
|
||||
}
|
||||
|
@ -80,12 +74,12 @@ public class ModUpdateAdapter extends RecyclerView.Adapter<ModUpdateAdapter.View
|
|||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
ButterKnife.bind(this, itemView);
|
||||
binding = UpdatableModListItemBinding.bind(view);
|
||||
binding.buttonUpdateMod.setOnClickListener(v -> onUpdateClick());
|
||||
}
|
||||
|
||||
@OnClick(R.id.button_update_mod)
|
||||
void onUpdateClick() {
|
||||
CommonLogic.doOnNonNull(CommonLogic.getActivityFromView(textModName), context -> CommonLogic.openUrl(context, updateInfo.getSuggestedUpdate().getUrl()));
|
||||
CommonLogic.doOnNonNull(CommonLogic.getActivityFromView(binding.textViewModName), context -> CommonLogic.openUrl(context, updateInfo.getSuggestedUpdate().getUrl()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.zane.smapiinstaller.R;
|
||||
import com.zane.smapiinstaller.databinding.FragmentModUpdateListBinding;
|
||||
import com.zane.smapiinstaller.dto.ModUpdateCheckResponseDto;
|
||||
import com.zane.smapiinstaller.logic.CommonLogic;
|
||||
import com.zane.smapiinstaller.utils.JsonUtil;
|
||||
|
@ -25,6 +25,8 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
*/
|
||||
public class ModUpdateFragment extends Fragment {
|
||||
|
||||
private FragmentModUpdateListBinding binding;
|
||||
|
||||
/**
|
||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||
* fragment (e.g. upon screen orientation changes).
|
||||
|
@ -35,23 +37,20 @@ public class ModUpdateFragment extends Fragment {
|
|||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_mod_update_list, container, false);
|
||||
|
||||
binding = FragmentModUpdateListBinding.inflate(inflater, container, false);
|
||||
// Set the adapter
|
||||
if (view instanceof RecyclerView) {
|
||||
Context context = view.getContext();
|
||||
RecyclerView recyclerView = (RecyclerView) view;
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
||||
Context context = binding.getRoot().getContext();
|
||||
RecyclerView recyclerView = binding.getRoot();
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
||||
|
||||
CommonLogic.doOnNonNull(this.getArguments(), arguments -> {
|
||||
String updateInfoListJson = ModUpdateFragmentArgs.fromBundle(arguments).getUpdateInfoListJson();
|
||||
List<ModUpdateCheckResponseDto> updateInfos = JsonUtil.fromJson(updateInfoListJson, new TypeReference<List<ModUpdateCheckResponseDto>>() {
|
||||
});
|
||||
ModUpdateAdapter adapter = new ModUpdateAdapter(updateInfos);
|
||||
recyclerView.setAdapter(adapter);
|
||||
CommonLogic.doOnNonNull(this.getArguments(), arguments -> {
|
||||
String updateInfoListJson = ModUpdateFragmentArgs.fromBundle(arguments).getUpdateInfoListJson();
|
||||
List<ModUpdateCheckResponseDto> updateInfos = JsonUtil.fromJson(updateInfoListJson, new TypeReference<List<ModUpdateCheckResponseDto>>() {
|
||||
});
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
|
||||
}
|
||||
return view;
|
||||
ModUpdateAdapter adapter = new ModUpdateAdapter(updateInfos);
|
||||
recyclerView.setAdapter(adapter);
|
||||
});
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
|
||||
return binding.getRoot();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.common.io.Files;
|
||||
import com.hjq.language.LanguagesManager;
|
||||
import com.microsoft.appcenter.crashes.Crashes;
|
||||
import com.smart.library.util.bspatch.BSPatchUtil;
|
||||
|
||||
import org.apache.commons.io.input.BOMInputStream;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -313,27 +310,4 @@ public class FileUtils extends org.zeroturnaround.zip.commons.FileUtils {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] patchFile(byte[] originBytes, byte[] patchBytes) {
|
||||
File patch = null;
|
||||
File origin = null;
|
||||
File patched = null;
|
||||
try {
|
||||
patch = File.createTempFile("patch", null);
|
||||
Files.write(patchBytes, patch);
|
||||
origin = File.createTempFile("origin", null);
|
||||
Files.write(originBytes, origin);
|
||||
patched = File.createTempFile("patched", null);
|
||||
if (BSPatchUtil.bspatch(origin.getAbsolutePath(), patched.getAbsolutePath(), patch.getAbsolutePath()) == 0) {
|
||||
return Files.asByteSource(patched).read();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Crashes.trackError(e);
|
||||
} finally {
|
||||
FileUtils.deleteQuietly(patch);
|
||||
FileUtils.deleteQuietly(origin);
|
||||
FileUtils.deleteQuietly(patched);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package com.zane.smapiinstaller.utils.function;
|
||||
|
||||
import android.text.Editable;
|
||||
|
||||
/**
|
||||
* @author Zane
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TextChangedWatcher extends android.text.TextWatcher {
|
||||
/**
|
||||
* Do nothing
|
||||
* @param s origin string
|
||||
* @param start modify position
|
||||
* @param count modify count
|
||||
* @param after modified string
|
||||
*/
|
||||
@Override
|
||||
default void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
/**
|
||||
* Text changed event
|
||||
* @param s modified string
|
||||
* @param start modify position
|
||||
* @param count modify count
|
||||
*/
|
||||
@Override
|
||||
void onTextChanged(CharSequence s, int start, int before, int count);
|
||||
|
||||
/**
|
||||
* Do nothing
|
||||
* @param s target view
|
||||
*/
|
||||
@Override
|
||||
default void afterTextChanged(Editable s) {}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
<include
|
||||
layout="@layout/app_bar_main"
|
||||
android:id="@+id/app_bar_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="settings_verbose_logging">Registro detallado</string>
|
||||
<string name="signing_package">Firmando paquete deinstalación</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">Versión SMAPI: 3.7.3.2</string>
|
||||
<string name="smapi_version">Versión SMAPI: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">Nota: Requiere la versión del juego 1.4.5.138 o superior</string>
|
||||
<string name="text_install_tip2">El cuerpo del juego debe instalarse durante la actualización o instalación</string>
|
||||
<string name="unpacking_smapi_files">Desempacando</string>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="settings_verbose_logging">Journalisation détaillée</string>
|
||||
<string name="signing_package">Signature</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">Version SMAPI: 3.7.3.2</string>
|
||||
<string name="smapi_version">Version SMAPI: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">Remarques: La version du jeu 1.4.5.138 ou ultérieure est requise.</string>
|
||||
<string name="text_install_tip2">Le jeu de base est requis lors de la mise à jour / installation.</string>
|
||||
<string name="unpacking_smapi_files">Déballage</string>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="settings_verbose_logging">Catatan Terperinci</string>
|
||||
<string name="signing_package">Menandatangani</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">Versi SMAPI: 3.7.3.2</string>
|
||||
<string name="smapi_version">Versi SMAPI: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">Catatan: Dibutuhkan Stardew Valley versi 1.4.5.138 atau yang lebih baru.</string>
|
||||
<string name="text_install_tip2">Permainan dasar diperlukan saat memperbarui/menginstal.</string>
|
||||
<string name="unpacking_smapi_files">Membongkar</string>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="settings_verbose_logging">자세한 로그</string>
|
||||
<string name="signing_package">설치 패키지 서명</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">SMAPI버전: 3.7.3.2</string>
|
||||
<string name="smapi_version">SMAPI버전: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">참고 : 게임 버전 1.4.5.138 이상이 필요합니다</string>
|
||||
<string name="text_install_tip2">업데이트 또는 설치 중에 게임 본체를 설치해야합니다</string>
|
||||
<string name="unpacking_smapi_files">포장 풀기</string>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="settings_verbose_logging">Log detalhado</string>
|
||||
<string name="signing_package">Assinatura</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">Versão SMAPI: 3.7.3.2</string>
|
||||
<string name="smapi_version">Versão SMAPI: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">Notas: É necessária a versão do jogo 1.4.5.138 ou posterior.</string>
|
||||
<string name="text_install_tip2">O jogo base é necessário ao atualizar / instalar.</string>
|
||||
<string name="unpacking_smapi_files">Desembalar</string>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="settings_verbose_logging">บันทึกอย่างละเอียด</string>
|
||||
<string name="signing_package">กำลังลงทะเบียนแอป</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">เวอร์ชั่น SMAPI: 3.7.3.2</string>
|
||||
<string name="smapi_version">เวอร์ชั่น SMAPI: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">หมายเหตุ: ต้องการเกมเวอร์ชั่น 1.4.5.138 หรือใหม่กว่า</string>
|
||||
<string name="text_install_tip2">ต้องการเกมหลักเมื่อทำการอัปเดต / ติดตั้ง</string>
|
||||
<string name="unpacking_smapi_files">กำลังแกะกล่อง</string>
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<string name="settings_verbose_logging">詳細日誌</string>
|
||||
<string name="signing_package">正在簽名安裝包</string>
|
||||
<string name="smapi_game_name">SMAPI 星露谷物語</string>
|
||||
<string name="smapi_version">SMAPI版本: 3.7.3.2</string>
|
||||
<string name="smapi_version">SMAPI版本: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">注意:需要 1.4.5.138 以上遊戲版本</string>
|
||||
<string name="text_install_tip2">更新或安裝期間需要安裝遊戲</string>
|
||||
<string name="unpacking_smapi_files">正在解包</string>
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<string name="settings_verbose_logging">详细日志</string>
|
||||
<string name="signing_package">正在签名安装包</string>
|
||||
<string name="smapi_game_name">SMAPI星露谷物语</string>
|
||||
<string name="smapi_version">SMAPI版本: 3.7.3.2</string>
|
||||
<string name="smapi_version">SMAPI版本: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">注意:需要不低于1.4.5.138版本的游戏本体</string>
|
||||
<string name="text_install_tip2">更新或安装期间需要安装游戏本体</string>
|
||||
<string name="unpacking_smapi_files">正在解包</string>
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<string name="settings_verbose_logging">Verbose Logging</string>
|
||||
<string name="signing_package">Signing</string>
|
||||
<string name="smapi_game_name">SMAPI Stardew Valley</string>
|
||||
<string name="smapi_version">SMAPI Version: 3.7.3.2</string>
|
||||
<string name="smapi_version">SMAPI Version: 3.7.3.3</string>
|
||||
<string name="text_install_tip1">Notes: Game version 1.4.5.138 or later is required.</string>
|
||||
<string name="text_install_tip2">The base game is required when updating/installing.</string>
|
||||
<string name="unpacking_smapi_files">Unpacking</string>
|
||||
|
|
Loading…
Reference in New Issue