diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce0ab5c6..bac0855e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,6 +90,7 @@ + diff --git a/app/src/main/assets/licenses/Android AppCompat Library V7 b/app/src/main/assets/licenses/Android AppCompat Library V7 new file mode 100644 index 00000000..b87d6ec7 --- /dev/null +++ b/app/src/main/assets/licenses/Android AppCompat Library V7 @@ -0,0 +1,13 @@ +Copyright (C) 2019 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/assets/licenses/Android Lifecycle Extensions b/app/src/main/assets/licenses/Android Lifecycle Extensions new file mode 100644 index 00000000..b87d6ec7 --- /dev/null +++ b/app/src/main/assets/licenses/Android Lifecycle Extensions @@ -0,0 +1,13 @@ +Copyright (C) 2019 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/assets/licenses/Android Support Preference V7 b/app/src/main/assets/licenses/Android Support Preference V7 new file mode 100644 index 00000000..b87d6ec7 --- /dev/null +++ b/app/src/main/assets/licenses/Android Support Preference V7 @@ -0,0 +1,13 @@ +Copyright (C) 2019 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/assets/licenses/Glide b/app/src/main/assets/licenses/Glide new file mode 100644 index 00000000..441c3743 --- /dev/null +++ b/app/src/main/assets/licenses/Glide @@ -0,0 +1,94 @@ +License for everything not in third_party and not otherwise marked: + +Copyright 2014 Google, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Google, Inc. +--------------------------------------------------------------------------------------------- +License for third_party/disklrucache: + +Copyright 2012 Jake Wharton +Copyright 2011 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--------------------------------------------------------------------------------------------- +License for third_party/gif_decoder: + +Copyright (c) 2013 Xcellent Creations, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------------------------------------------- +License for third_party/gif_encoder/AnimatedGifEncoder.java and +third_party/gif_encoder/LZWEncoder.java: + +No copyright asserted on the source code of this class. May be used for any +purpose, however, refer to the Unisys LZW patent for restrictions on use of +the associated LZWEncoder class. Please forward any corrections to +kweiner@fmsware.com. + +----------------------------------------------------------------------------- +License for third_party/gif_encoder/NeuQuant.java + +Copyright (c) 1994 Anthony Dekker + +NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See +"Kohonen neural networks for optimal colour quantization" in "Network: +Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of +the algorithm. + +Any party obtaining a copy of these files from the author, directly or +indirectly, is granted, free of charge, a full and unrestricted irrevocable, +world-wide, paid up, royalty-free, nonexclusive right and license to deal in +this software and documentation files (the "Software"), including without +limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons who +receive copies from any such party to do so, with the only requirement being +that this copyright notice remain intact. \ No newline at end of file diff --git a/app/src/main/assets/licenses/Material Components for Android b/app/src/main/assets/licenses/Material Components for Android new file mode 100644 index 00000000..b87d6ec7 --- /dev/null +++ b/app/src/main/assets/licenses/Material Components for Android @@ -0,0 +1,13 @@ +Copyright (C) 2019 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/assets/licenses/PseudoApkSigner b/app/src/main/assets/licenses/PseudoApkSigner new file mode 100644 index 00000000..1a0c97c6 --- /dev/null +++ b/app/src/main/assets/licenses/PseudoApkSigner @@ -0,0 +1,13 @@ +Copyright (C) 2019 Aefyr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/assets/licenses/Shizuku b/app/src/main/assets/licenses/Shizuku new file mode 100644 index 00000000..e5e78495 --- /dev/null +++ b/app/src/main/assets/licenses/Shizuku @@ -0,0 +1,13 @@ +Copyright (C) 2019 Rikka + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/assets/licenses/android-filepicker b/app/src/main/assets/licenses/android-filepicker new file mode 100644 index 00000000..9d5b7e83 --- /dev/null +++ b/app/src/main/assets/licenses/android-filepicker @@ -0,0 +1,13 @@ +Copyright (C) 2016 Angad Singh + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/app/src/main/java/com/aefyr/sai/adapters/LicensesAdapter.java b/app/src/main/java/com/aefyr/sai/adapters/LicensesAdapter.java new file mode 100644 index 00000000..0359c8f8 --- /dev/null +++ b/app/src/main/java/com/aefyr/sai/adapters/LicensesAdapter.java @@ -0,0 +1,66 @@ +package com.aefyr.sai.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.aefyr.sai.R; +import com.aefyr.sai.model.licenses.License; + +import java.util.List; + +public class LicensesAdapter extends RecyclerView.Adapter { + + private LayoutInflater mInflater; + + private List mLicenses; + + public LicensesAdapter(Context c) { + mInflater = LayoutInflater.from(c); + } + + public void setLicenses(List licenses) { + mLicenses = licenses; + notifyDataSetChanged(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new ViewHolder(mInflater.inflate(R.layout.item_license, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + holder.bind(mLicenses.get(position)); + } + + @Override + public int getItemCount() { + return mLicenses == null ? 0 : mLicenses.size(); + } + + class ViewHolder extends RecyclerView.ViewHolder { + + private TextView mSubject; + private TextView mText; + + private ViewHolder(@NonNull View itemView) { + super(itemView); + + mSubject = itemView.findViewById(R.id.tv_subject); + mText = itemView.findViewById(R.id.tv_text); + } + + private void bind(License license) { + mSubject.setText(license.subject); + mText.setText(license.text); + } + } + +} diff --git a/app/src/main/java/com/aefyr/sai/model/licenses/License.java b/app/src/main/java/com/aefyr/sai/model/licenses/License.java new file mode 100644 index 00000000..f4fab0f9 --- /dev/null +++ b/app/src/main/java/com/aefyr/sai/model/licenses/License.java @@ -0,0 +1,13 @@ +package com.aefyr.sai.model.licenses; + +public class License { + + public String subject; + public String text; + + public License(String subject, String text) { + this.subject = subject; + this.text = text; + } + +} diff --git a/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java b/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java index 00c1ade6..5f65c354 100644 --- a/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java +++ b/app/src/main/java/com/aefyr/sai/ui/activities/AboutActivity.java @@ -18,6 +18,7 @@ protected void onCreate(Bundle savedInstanceState) { ((TextView) findViewById(R.id.tv_about_app)).setText(String.format("%s %s", getString(R.string.app_name_full), BuildConfig.VERSION_NAME)); findViewById(R.id.button_about_source).setOnClickListener((v) -> openLink(getString(R.string.about_source_link))); findViewById(R.id.button_about_donate).setOnClickListener((v) -> openLink(getString(R.string.about_donate_link))); + findViewById(R.id.button_about_licenses).setOnClickListener((v) -> startActivity(new Intent(this, LicensesActivity.class))); } private void openLink(String link) { diff --git a/app/src/main/java/com/aefyr/sai/ui/activities/LicensesActivity.java b/app/src/main/java/com/aefyr/sai/ui/activities/LicensesActivity.java new file mode 100644 index 00000000..d4a16050 --- /dev/null +++ b/app/src/main/java/com/aefyr/sai/ui/activities/LicensesActivity.java @@ -0,0 +1,32 @@ +package com.aefyr.sai.ui.activities; + +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProviders; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.aefyr.sai.R; +import com.aefyr.sai.adapters.LicensesAdapter; +import com.aefyr.sai.viewmodels.LicensesViewModel; + +public class LicensesActivity extends ThemedActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_licenses); + + RecyclerView recyclerView = findViewById(R.id.rv_licenses); + + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.getRecycledViewPool().setMaxRecycledViews(0, 16); + + LicensesAdapter adapter = new LicensesAdapter(this); + recyclerView.setAdapter(adapter); + + LicensesViewModel viewModel = ViewModelProviders.of(this).get(LicensesViewModel.class); + viewModel.getLicenses().observe(this, adapter::setLicenses); + } +} diff --git a/app/src/main/java/com/aefyr/sai/utils/IOUtils.java b/app/src/main/java/com/aefyr/sai/utils/IOUtils.java index fbb9f00f..44b4ebe7 100644 --- a/app/src/main/java/com/aefyr/sai/utils/IOUtils.java +++ b/app/src/main/java/com/aefyr/sai/utils/IOUtils.java @@ -4,6 +4,7 @@ import android.util.Log; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -11,6 +12,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.nio.charset.Charset; import java.util.zip.CRC32; public class IOUtils { @@ -75,4 +77,11 @@ public static Thread writeStreamToStringBuilder(StringBuilder builder, InputStre return t; } + public static String readStream(InputStream aInputStream, Charset charset) throws IOException { + try (InputStream inputStream = aInputStream; ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + copyStream(inputStream, outputStream); + return new String(outputStream.toByteArray(), charset); + } + } + } diff --git a/app/src/main/java/com/aefyr/sai/viewmodels/LicensesViewModel.java b/app/src/main/java/com/aefyr/sai/viewmodels/LicensesViewModel.java new file mode 100644 index 00000000..a5edd525 --- /dev/null +++ b/app/src/main/java/com/aefyr/sai/viewmodels/LicensesViewModel.java @@ -0,0 +1,70 @@ +package com.aefyr.sai.viewmodels; + +import android.app.Application; +import android.content.res.AssetManager; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.aefyr.sai.model.licenses.License; +import com.aefyr.sai.utils.IOUtils; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class LicensesViewModel extends AndroidViewModel { + + private MutableLiveData> mLicenses = new MutableLiveData<>(); + private MutableLiveData mAreLicensesLoading = new MutableLiveData<>(); + + public LicensesViewModel(@NonNull Application application) { + super(application); + + mLicenses.setValue(Collections.emptyList()); + mAreLicensesLoading.setValue(false); + + loadLicences(); + } + + public LiveData> getLicenses() { + return mLicenses; + } + + public LiveData getAreLicensesLoading() { + return mAreLicensesLoading; + } + + private void loadLicences() { + if (mAreLicensesLoading.getValue()) + return; + + mAreLicensesLoading.setValue(true); + + new Thread(() -> { + try { + AssetManager assetManager = getApplication().getAssets(); + String licensesDir = "licenses"; + + String[] rawLicenses = assetManager.list(licensesDir); + ArrayList licenses = new ArrayList<>(rawLicenses.length); + + for (String rawLicense : rawLicenses) + licenses.add(new License(rawLicense, IOUtils.readStream(assetManager.open(licensesDir + "/" + rawLicense), StandardCharsets.UTF_8))); + + Collections.sort(licenses, (license1, license2) -> license1.subject.compareToIgnoreCase(license2.subject)); + + mLicenses.postValue(licenses); + mAreLicensesLoading.postValue(false); + } catch (Exception e) { + Log.wtf("Licenses", e); + mAreLicensesLoading.postValue(false); + } + }).start(); + } + +} diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 62abba79..4681234f 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -52,6 +52,12 @@ android:layout_margin="8dp" android:text="@string/about_source" /> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_license.xml b/app/src/main/res/layout/item_license.xml new file mode 100644 index 00000000..49cb9747 --- /dev/null +++ b/app/src/main/res/layout/item_license.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 16d2b92a..0c7c9ae8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -88,5 +88,6 @@ GitHub Поддержать + Лицензии \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 556964e5..143f2523 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -93,5 +93,6 @@ https://github.com/Aefyr/SAI Donate https://yasobe.ru/na/sai + Licenses