Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e10cc5d11 | ||
|
|
f06b6d442f | ||
|
|
4fd8832d90 | ||
|
|
61e3d49670 | ||
|
|
8610ad9a03 | ||
|
|
83f9bcdf88 | ||
|
|
0d7ea6174d | ||
|
|
5aab372920 | ||
|
|
32e5bfa36d | ||
|
|
3a90b17301 | ||
|
|
b706f679a9 | ||
|
|
6f4cf5674e | ||
|
|
3ffba02332 | ||
|
|
937791eb5c | ||
|
|
568c0044a4 | ||
|
|
070fe0a620 | ||
|
|
38d78a8e6a |
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
11
.github/ISSUE_TEMPLATE/give-me-some-idea-for-this-app.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/give-me-some-idea-for-this-app.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: Give Me Some Idea For This App
|
||||||
|
about: If your idea is unique i will definitely implement the Idea and mention you
|
||||||
|
in my repo and add the feature to the app
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
168
README.md
168
README.md
@@ -1,15 +1,14 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="app/src/main/assets/logo.png" alt="Calculator Hide File App Logo" width="200" />
|
<img src="app/src/main/assets/logo.png" alt="Calculator Hide File App Logo" width="200" />
|
||||||
|
|
||||||
|
# 📂 Calculator Hide File App for Android 📂
|
||||||
# Calculator Hide File App
|
|
||||||
|
|
||||||
<a href="https://github.com/Binondi/Calculator-Hide-Files/releases/latest">
|
<a href="https://github.com/Binondi/Calculator-Hide-Files/releases/latest">
|
||||||
<img alt="Latest release" src="https://img.shields.io/badge/Releases-v1.0-blue?logo=github&style=for-the-badge">
|
<img alt="Latest release" src="https://img.shields.io/badge/Releases-v1.0-blue?logo=github&style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://github.com/Binondi/Calculator-Hide-Files/releases/latest">
|
<a href="https://github.com/Binondi/Calculator-Hide-Files/releases/latest">
|
||||||
<img alt="Downloads" src="https://img.shields.io/badge/Downloads-1.2k-blue?logo=github&style=for-the-badge">
|
<img alt="Downloads" src="https://img.shields.io/badge/Downloads-1.3k-blue?logo=github&style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="LICENSE">
|
<a href="LICENSE">
|
||||||
@@ -19,132 +18,137 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
Welcome to the **Calculator Hide File App**! This app is a unique and secure way to hide your sensitive files under the disguise of a fully functional calculator.
|
|
||||||
|
## 😍 Why Choose This App?
|
||||||
|
The **Calculator Hide File App** is an **open-source** application, allowing you to inspect the code yourself. This ensures **complete transparency** and guarantees that your **privacy remains uncompromised**. 🔒✅
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Features
|
## 🔥 About Calculator Hide File App
|
||||||
|
|
||||||
- **Dual Functionality**: Operates as a regular calculator and a file hiding app.
|
The **Calculator Hide File App** is an innovative **Android file-hiding app** that disguises itself as a **fully functional calculator**. It helps you **securely store** private files and protect them with a **hidden passcode**.
|
||||||
- **User-Friendly Interface**: Simple and intuitive design for easy use.
|
|
||||||
- **Secure File Storage**: Protects your hidden files with a passcode.
|
> **⭐ Why Choose This App?**
|
||||||
- **Passcode Protection**: Access the hidden files by entering a secret passcode in the calculator.
|
> - Hide images, videos, documents & other files securely.
|
||||||
- **File Management**: Easily hide, unhide, and manage files within the app.
|
> - Works like a **real calculator** with hidden storage mode.
|
||||||
|
> - No one will suspect it’s a file vault!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Screenshots
|
## 🚀 Features
|
||||||
<div>
|
|
||||||
|
|
||||||
<img src="app/src/main/assets/Screenshot_1.jpg" alt="Screenshot 1" width="24%">
|
✅ **Dual Functionality** – A working **calculator** & a **file vault** in one app.
|
||||||
<img src="app/src/main/assets/Screenshot_2.jpg" alt="Screenshot 2" width="24%">
|
✅ **Secret Passcode** – Unlock hidden files by entering a secret code.
|
||||||
<img src="app/src/main/assets/Screenshot_3.jpg" alt="Screenshot 3" width="24%">
|
✅ **Secure File Manager** – Hide/unhide files easily.
|
||||||
<img src="app/src/main/assets/Screenshot_4.jpg" alt="Screenshot 4" width="24%">
|
✅ **Fast & Lightweight** – Smooth performance on all Android devices.
|
||||||
|
✅ **No Root Required** – Works without rooting your phone.
|
||||||
|
|
||||||
</div>
|
---
|
||||||
<div>
|
|
||||||
<img src="app/src/main/assets/Screenshot_5.jpg" alt="Screenshot 5" width="24%">
|
## 🖼️ Screenshots
|
||||||
<img src="app/src/main/assets/Screenshot_6.jpg" alt="Screenshot 6" width="24%">
|
|
||||||
<img src="app/src/main/assets/Screenshot_7.jpg" alt="Screenshot 7" width="24%">
|
<div align="center">
|
||||||
<img src="app/src/main/assets/Screenshot_8.jpg" alt="Screenshot 8" width="24%">
|
<img src="app/src/main/assets/Screenshot_1.jpg" alt="Calculator Hide File App - Home Screen" width="24%">
|
||||||
|
<img src="app/src/main/assets/Screenshot_2.jpg" alt="Calculator Hide File App - Secure File Storage" width="24%">
|
||||||
|
<img src="app/src/main/assets/Screenshot_3.jpg" alt="Calculator Hide File App - Passcode Protection" width="24%">
|
||||||
|
<img src="app/src/main/assets/Screenshot_4.jpg" alt="Calculator Hide File App - Hidden Files Manager" width="24%">
|
||||||
</div>
|
</div>
|
||||||
---
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
1. **Calculator Mode**:
|
|
||||||
- Perform basic arithmetic operations just like any regular calculator.
|
|
||||||
2. **Setup Password**:
|
|
||||||
- Enter `123456=` to setup your password.
|
|
||||||
3. **Hidden Mode**:
|
|
||||||
- Enter your secret passcode and hit the `=` button to unlock the hidden file manager.
|
|
||||||
5. **File Management**:
|
|
||||||
- Add files to hide them securely.
|
|
||||||
- Retrieve or unhide files as needed.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ☕ Support
|
## 🔑 How It Works
|
||||||
|
|
||||||
Support My development by donating money. Thank you very much for your help! ❤️
|
1. **Use as a Regular Calculator**
|
||||||
|
- Perform standard arithmetic operations like a normal calculator.
|
||||||
|
|
||||||
[<img src="https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA"
|
2. **Enter Secret Passcode**
|
||||||
alt="Sponsor the project on GitHub"
|
- Type `123456` and press `=` to set up your password.
|
||||||
height="40">](https://github.com/sponsors/Binondi/Calculator-Hide-Files) [<img src="https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white"
|
- Enter your **custom passcode** and hit `=` to unlock the hidden file manager.
|
||||||
alt="Donate with PayPal"
|
|
||||||
height="40">](https://www.paypal.me/BinondiBorthakur56) [<img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black"
|
|
||||||
alt="Donate with buymeacoffee"
|
|
||||||
height="40">](https://buymeacoffee.com/binondi)
|
|
||||||
|
|
||||||
|
3. **Manage Hidden Files**
|
||||||
---
|
- Add, remove, and restore hidden files.
|
||||||
## Installation
|
- Files stay protected even after closing the app.
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Android Studio (for development)
|
|
||||||
- A device or emulator running Android 6.0 or higher
|
|
||||||
|
|
||||||
### Steps
|
|
||||||
1. Clone the repository:
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/YourUsername/CalculatorHideFileApp.git
|
|
||||||
```
|
|
||||||
2. Open the project in Android Studio.
|
|
||||||
3. Build and run the app on your device or emulator.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Technologies Used
|
## 📥 Download & Installation
|
||||||
|
|
||||||
- **Programming Language**: Java/Kotlin
|
### 🔗 **[Download the Latest Version Here](https://github.com/Binondi/Calculator-Hide-Files/releases/latest)**
|
||||||
- **Development Platform**: Android Studio
|
|
||||||
- **UI Framework**: Android XML layouts
|
### 🔹 Prerequisites
|
||||||
- **File Storage**: Secure internal storage and MediaStore API
|
- **Android 6.0 or higher**
|
||||||
|
- **Storage permissions enabled**
|
||||||
|
|
||||||
|
### 🔹 Installation Steps
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Binondi/Calculator-Hide-Files.git
|
||||||
|
```
|
||||||
|
- Open **Android Studio** and build the project.
|
||||||
|
- Install the APK on your **Android device or emulator**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage Instructions
|
## 🛠️ Technologies Used
|
||||||
|
|
||||||
1. Open the app.
|
- **Programming Language**: Kotlin
|
||||||
2. Use the calculator as normal.
|
- **UI Framework**: XML (For UI)
|
||||||
3. Enter the secret passcode and press `=` to switch to the hidden file manager.
|
- **File Storage**: Secure internal storage & MediaStore API
|
||||||
4. Add or manage your hidden files.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Contributing
|
## 🎯 Why Use Calculator Hide File App?
|
||||||
|
|
||||||
|
- **No One Can Detect Your Files** – Works like a real calculator.
|
||||||
|
- **100% Secure** – Your private files stay hidden, even if someone opens the app.
|
||||||
|
- **Completely Free & Open Source** – Modify or contribute to the project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❤️ Support the Project
|
||||||
|
|
||||||
|
If you find this app useful, please consider supporting the development. 🙏
|
||||||
|
|
||||||
|
[](https://github.com/sponsors/Binondi)
|
||||||
|
[](https://paypal.me/BinondiBorthakur56)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Contributing
|
||||||
|
|
||||||
We welcome contributions! To contribute:
|
We welcome contributions! To contribute:
|
||||||
|
|
||||||
1. Fork the repository.
|
1. **Fork the repository**
|
||||||
2. Create a new branch for your feature or bugfix:
|
2. **Create a new branch**
|
||||||
```bash
|
```bash
|
||||||
git checkout -b feature-name
|
git checkout -b feature-name
|
||||||
```
|
```
|
||||||
3. Commit your changes:
|
3. **Commit your changes**
|
||||||
```bash
|
```bash
|
||||||
git commit -m "Add a new feature"
|
git commit -m "Add a new feature"
|
||||||
```
|
```
|
||||||
4. Push to the branch:
|
4. **Push to GitHub**
|
||||||
```bash
|
```bash
|
||||||
git push origin feature-name
|
git push origin feature-name
|
||||||
```
|
```
|
||||||
5. Open a Pull Request.
|
5. **Create a Pull Request**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## License
|
## 📜 License
|
||||||
|
|
||||||
This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
|
This project is licensed under the **Apache License 2.0**.
|
||||||
|
See the full license [here](LICENSE).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Contact
|
## 📧 Contact
|
||||||
|
|
||||||
For any inquiries or feedback, reach out to:
|
For any questions or feedback:
|
||||||
- **Email**: binondiborthakur56@gmail.com
|
📩 **Email**: binondiborthakur56@gmail.com
|
||||||
- **GitHub**: [Binondi](https://github.com/Binondi)
|
🐙 **GitHub**: [Binondi](https://github.com/Binondi)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Thank you for using the **Calculator Hide File App**! We hope you find it secure and easy to use.
|
### 🎉 Thank You for Using Calculator Hide File App! 🎉
|
||||||
|
🚀 **Keep your files secure and hidden!** 🚀
|
||||||
|
|||||||
@@ -11,15 +11,22 @@ android {
|
|||||||
applicationId = "devs.org.calculator"
|
applicationId = "devs.org.calculator"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 1
|
versionCode = 3
|
||||||
versionName = "1.0"
|
versionName = "1.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = true
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
isMinifyEnabled = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
@@ -45,15 +52,16 @@ dependencies {
|
|||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.constraintlayout)
|
implementation(libs.androidx.constraintlayout)
|
||||||
|
implementation(libs.androidx.gridlayout)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|
||||||
//custom dependencies
|
//custom dependencies
|
||||||
implementation(libs.exp4j)
|
implementation(libs.exp4j)
|
||||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
implementation(libs.glide)
|
||||||
implementation("androidx.documentfile:documentfile:1.0.1")
|
implementation(libs.androidx.documentfile)
|
||||||
implementation("com.github.chrisbanes:PhotoView:2.3.0")
|
implementation(libs.photoview)
|
||||||
implementation("androidx.viewpager:viewpager:1.0.0")
|
implementation(libs.androidx.viewpager)
|
||||||
implementation("com.jsibbold:zoomage:1.3.1")
|
implementation(libs.zoomage)
|
||||||
}
|
}
|
||||||
85
app/proguard-rules.pro
vendored
85
app/proguard-rules.pro
vendored
@@ -1,21 +1,70 @@
|
|||||||
# Add project specific ProGuard rules here.
|
# Keep your MainActivity and Application class
|
||||||
# You can control the set of applied configuration files using the
|
-keep public class devs.org.calculator.activities.MainActivity
|
||||||
# proguardFiles setting in build.gradle.
|
-keep public class devs.org.calculator.activities.SetupPasswordActivity
|
||||||
#
|
-keep public class devs.org.calculator.activities.HiddenVaultActivity
|
||||||
# For more details, see
|
-keep public class devs.org.calculator.** { *; }
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
# Keep exp4j library since it's used for expression evaluation
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
-keep class net.objecthunter.exp4j.** { *; }
|
||||||
# class:
|
-dontwarn net.objecthunter.exp4j.**
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
# Keep Google Material components
|
||||||
# debugging stack traces.
|
-keep class com.google.android.material.** { *; }
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
-dontwarn com.google.android.material.**
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
# Keep Android X components
|
||||||
# hide the original source file name.
|
-keep class androidx.** { *; }
|
||||||
#-renamesourcefileattribute SourceFile
|
-keep interface androidx.** { *; }
|
||||||
|
|
||||||
|
# Keep any classes with ViewBinding
|
||||||
|
-keep class devs.org.calculator.databinding.** { *; }
|
||||||
|
|
||||||
|
# Keep any callback interfaces
|
||||||
|
-keep class devs.org.calculator.callbacks.** { *; }
|
||||||
|
-keep interface devs.org.calculator.callbacks.** { *; }
|
||||||
|
|
||||||
|
# Keep classes used for regex pattern matching
|
||||||
|
-keep class java.util.regex.** { *; }
|
||||||
|
|
||||||
|
# Keep annotation classes
|
||||||
|
-keepattributes *Annotation*
|
||||||
|
-keepattributes Signature
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# Keep Parcelable classes (might be needed for Intent extras)
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Keep FileManager classes since they work with storage permissions
|
||||||
|
-keep class devs.org.calculator.utils.FileManager { *; }
|
||||||
|
|
||||||
|
# Keep DialogUtil since it's used for permission dialogs
|
||||||
|
-keep class devs.org.calculator.utils.DialogUtil { *; }
|
||||||
|
|
||||||
|
# Keep PrefsUtil since it's used for password validation
|
||||||
|
-keep class devs.org.calculator.utils.PrefsUtil { *; }
|
||||||
|
|
||||||
|
# General Android rules
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Keep any classes that use reflection
|
||||||
|
-keepattributes InnerClasses
|
||||||
|
|
||||||
|
# Keep R classes and their fields
|
||||||
|
-keepclassmembers class **.R$* {
|
||||||
|
public static <fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Keep enums
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Keep specific activities with special code in onCreate
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void onCreate(android.os.Bundle);
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import android.widget.Toast
|
|||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.callbacks.FileProcessCallback
|
import devs.org.calculator.callbacks.FileProcessCallback
|
||||||
import devs.org.calculator.utils.FileManager
|
import devs.org.calculator.utils.FileManager
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -43,7 +44,7 @@ class AudioGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
).processMultipleFiles(uriList, fileType, this@AudioGalleryActivity)
|
).processMultipleFiles(uriList, fileType, this@AudioGalleryActivity)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "No files selected", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.no_files_selected), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ class AudioGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this@AudioGalleryActivity,
|
this@AudioGalleryActivity,
|
||||||
"${copiedFiles.size} Audios hidden successfully",
|
"${copiedFiles.size} ${getString(R.string.audio_hidded_successfully)} ",
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
loadFiles()
|
loadFiles()
|
||||||
@@ -78,7 +79,7 @@ class AudioGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun openPreview() {
|
override fun openPreview() {
|
||||||
// Implement audio preview
|
// Not implemented audio preview
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package devs.org.calculator.activities
|
package devs.org.calculator.activities
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@@ -8,11 +9,13 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
import android.view.View
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.IntentSenderRequest
|
import androidx.activity.result.IntentSenderRequest
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.adapters.FileAdapter
|
import devs.org.calculator.adapters.FileAdapter
|
||||||
import devs.org.calculator.databinding.ActivityGalleryBinding
|
import devs.org.calculator.databinding.ActivityGalleryBinding
|
||||||
import devs.org.calculator.utils.FileManager
|
import devs.org.calculator.utils.FileManager
|
||||||
@@ -20,9 +23,9 @@ import java.io.File
|
|||||||
|
|
||||||
abstract class BaseGalleryActivity : AppCompatActivity() {
|
abstract class BaseGalleryActivity : AppCompatActivity() {
|
||||||
protected lateinit var binding: ActivityGalleryBinding
|
protected lateinit var binding: ActivityGalleryBinding
|
||||||
protected lateinit var fileManager: FileManager
|
private lateinit var fileManager: FileManager
|
||||||
protected lateinit var adapter: FileAdapter
|
private lateinit var adapter: FileAdapter
|
||||||
protected lateinit var files: List<File>
|
private lateinit var files: List<File>
|
||||||
|
|
||||||
private lateinit var intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
|
private lateinit var intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||||
private val storagePermissionLauncher = registerForActivityResult(
|
private val storagePermissionLauncher = registerForActivityResult(
|
||||||
@@ -38,6 +41,7 @@ abstract class BaseGalleryActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
abstract val fileType: FileManager.FileType
|
abstract val fileType: FileManager.FileType
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setupIntentSenderLauncher()
|
setupIntentSenderLauncher()
|
||||||
@@ -46,18 +50,27 @@ abstract class BaseGalleryActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
fileManager = FileManager(this, this)
|
fileManager = FileManager(this, this)
|
||||||
|
|
||||||
binding.fabAdd.text = when(fileType){
|
when(fileType){
|
||||||
FileManager.FileType.IMAGE -> {
|
FileManager.FileType.IMAGE -> {
|
||||||
"Add Image"
|
val image = getString(R.string.add_image)
|
||||||
|
binding.fabAdd.text = image
|
||||||
|
binding.noItemsTxt.text = "${getString(R.string.no_items_available_add_one_by_clicking_on_the_plus_button)} '$image' button"
|
||||||
}
|
}
|
||||||
FileManager.FileType.AUDIO -> {
|
FileManager.FileType.AUDIO -> {
|
||||||
"Add Audio"
|
val text = getString(R.string.add_audio)
|
||||||
|
binding.fabAdd.text = text
|
||||||
|
binding.noItemsTxt.text = "${getString(R.string.no_items_available_add_one_by_clicking_on_the_plus_button)} '$text' button"
|
||||||
|
|
||||||
}
|
}
|
||||||
FileManager.FileType.VIDEO -> {
|
FileManager.FileType.VIDEO -> {
|
||||||
"Add Video"
|
val text = getString(R.string.add_video)
|
||||||
|
binding.fabAdd.text = text
|
||||||
|
binding.noItemsTxt.text = "${getString(R.string.no_items_available_add_one_by_clicking_on_the_plus_button)} '$text' button"
|
||||||
}
|
}
|
||||||
FileManager.FileType.DOCUMENT -> {
|
FileManager.FileType.DOCUMENT -> {
|
||||||
"Add Files"
|
val text = getString(R.string.add_files)
|
||||||
|
binding.fabAdd.text = text
|
||||||
|
binding.noItemsTxt.text = "${getString(R.string.no_items_available_add_one_by_clicking_on_the_plus_button)} '$text' button"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.recyclerView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
binding.recyclerView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
||||||
@@ -115,6 +128,15 @@ abstract class BaseGalleryActivity : AppCompatActivity() {
|
|||||||
protected open fun loadFiles() {
|
protected open fun loadFiles() {
|
||||||
files = fileManager.getFilesInHiddenDir(fileType)
|
files = fileManager.getFilesInHiddenDir(fileType)
|
||||||
adapter.submitList(files)
|
adapter.submitList(files)
|
||||||
|
if (files.isEmpty()){
|
||||||
|
binding.recyclerView.visibility = View.GONE
|
||||||
|
binding.loading.visibility = View.GONE
|
||||||
|
binding.noItems.visibility = View.VISIBLE
|
||||||
|
}else{
|
||||||
|
binding.recyclerView.visibility = View.VISIBLE
|
||||||
|
binding.loading.visibility = View.GONE
|
||||||
|
binding.noItems.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@@ -128,6 +150,7 @@ abstract class BaseGalleryActivity : AppCompatActivity() {
|
|||||||
// permission denied
|
// permission denied
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method has been deprecated in favor of using the Activity Result API\n which brings increased type safety via an {@link ActivityResultContract} and the prebuilt\n contracts for common intents available in\n {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for\n testing, and allow receiving results in separate, testable classes independent from your\n activity. Use\n {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}\n with the appropriate {@link ActivityResultContract} and handling the result in the\n {@link ActivityResultCallback#onActivityResult(Object) callback}.")
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
if (requestCode == 2296 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (requestCode == 2296 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.widget.Toast
|
|||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.utils.FileManager
|
import devs.org.calculator.utils.FileManager
|
||||||
import devs.org.calculator.callbacks.FileProcessCallback
|
import devs.org.calculator.callbacks.FileProcessCallback
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -15,7 +16,6 @@ import java.io.File
|
|||||||
class DocumentsActivity : BaseGalleryActivity(), FileProcessCallback {
|
class DocumentsActivity : BaseGalleryActivity(), FileProcessCallback {
|
||||||
override val fileType = FileManager.FileType.DOCUMENT
|
override val fileType = FileManager.FileType.DOCUMENT
|
||||||
private lateinit var pickLauncher: ActivityResultLauncher<Intent>
|
private lateinit var pickLauncher: ActivityResultLauncher<Intent>
|
||||||
private var selectedUri: Uri? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -40,19 +40,21 @@ class DocumentsActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
FileManager(this@DocumentsActivity, this@DocumentsActivity).processMultipleFiles(uriList, fileType,this@DocumentsActivity )
|
FileManager(this@DocumentsActivity, this@DocumentsActivity).processMultipleFiles(uriList, fileType,this@DocumentsActivity )
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "No files selected", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.no_files_selected), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
||||||
Toast.makeText(this@DocumentsActivity, "${copiedFiles.size} Documents hidden successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@DocumentsActivity,"${copiedFiles.size} ${getString(R.string.documents_hidden_successfully )}"
|
||||||
|
, Toast.LENGTH_SHORT).show()
|
||||||
loadFiles()
|
loadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFileProcessFailed() {
|
override fun onFileProcessFailed() {
|
||||||
Toast.makeText(this@DocumentsActivity, "Failed to hide Documents", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@DocumentsActivity,
|
||||||
|
getString(R.string.failed_to_hide_documents), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupFabButton() {
|
private fun setupFabButton() {
|
||||||
@@ -70,6 +72,6 @@ class DocumentsActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun openPreview() {
|
override fun openPreview() {
|
||||||
// Implement document preview
|
//Not implemented document preview
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ import devs.org.calculator.utils.FileManager
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.callbacks.FileProcessCallback
|
import devs.org.calculator.callbacks.FileProcessCallback
|
||||||
|
|
||||||
class ImageGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
class ImageGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
||||||
@@ -33,7 +34,8 @@ class ImageGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
setupFabButton()
|
setupFabButton()
|
||||||
|
|
||||||
intentSenderLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){
|
intentSenderLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){
|
||||||
if (it.resultCode != RESULT_OK) Toast.makeText(this, "Failed to hide/unhide photo", Toast.LENGTH_SHORT).show()
|
if (it.resultCode != RESULT_OK) Toast.makeText(this,
|
||||||
|
getString(R.string.failed_to_hide_unhide_photo), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
pickImageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
pickImageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
@@ -56,7 +58,7 @@ class ImageGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
.processMultipleFiles(uriList, fileType,this@ImageGalleryActivity )
|
.processMultipleFiles(uriList, fileType,this@ImageGalleryActivity )
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "No files selected", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.no_files_selected), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,12 +66,13 @@ class ImageGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
||||||
Toast.makeText(this@ImageGalleryActivity, "${copiedFiles.size} Images hidden successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@ImageGalleryActivity, "${copiedFiles.size} ${getString(R.string.images_hidden_successfully)}", Toast.LENGTH_SHORT).show()
|
||||||
loadFiles()
|
loadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFileProcessFailed() {
|
override fun onFileProcessFailed() {
|
||||||
Toast.makeText(this@ImageGalleryActivity, "Failed to hide images", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@ImageGalleryActivity,
|
||||||
|
getString(R.string.failed_to_hide_images), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupIntentSenderLauncher() {
|
private fun setupIntentSenderLauncher() {
|
||||||
@@ -125,9 +128,11 @@ class ImageGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
if (requestCode == STORAGE_PERMISSION_CODE) {
|
if (requestCode == STORAGE_PERMISSION_CODE) {
|
||||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Toast.makeText(this, "Storage permissions granted", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this,
|
||||||
|
getString(R.string.storage_permissions_granted), Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "Storage permissions denied", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this,
|
||||||
|
getString(R.string.storage_permissions_denied), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package devs.org.calculator.activities
|
package devs.org.calculator.activities
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@@ -20,12 +21,14 @@ import devs.org.calculator.utils.DialogUtil
|
|||||||
import devs.org.calculator.utils.FileManager
|
import devs.org.calculator.utils.FileManager
|
||||||
import devs.org.calculator.utils.PrefsUtil
|
import devs.org.calculator.utils.PrefsUtil
|
||||||
import net.objecthunter.exp4j.ExpressionBuilder
|
import net.objecthunter.exp4j.ExpressionBuilder
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
private var currentExpression = "0"
|
private var currentExpression = "0"
|
||||||
private var lastWasOperator = false
|
private var lastWasOperator = false
|
||||||
private var hasDecimal = false
|
private var hasDecimal = false
|
||||||
|
private var lastWasPercent = false
|
||||||
private lateinit var launcher: ActivityResultLauncher<Intent>
|
private lateinit var launcher: ActivityResultLauncher<Intent>
|
||||||
private lateinit var baseDocumentTreeUri: Uri
|
private lateinit var baseDocumentTreeUri: Uri
|
||||||
private val dialogUtil = DialogUtil(this)
|
private val dialogUtil = DialogUtil(this)
|
||||||
@@ -71,7 +74,7 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
binding.btnClear.setOnClickListener { clearDisplay() }
|
binding.btnClear.setOnClickListener { clearDisplay() }
|
||||||
binding.btnDot.setOnClickListener { addDecimal() }
|
binding.btnDot.setOnClickListener { addDecimal() }
|
||||||
binding.btnEquals.setOnClickListener { calculateResult() }
|
binding.btnEquals.setOnClickListener { calculateResult() }
|
||||||
binding.btnPercent.setOnClickListener { calculatePercentage() }
|
binding.btnPercent.setOnClickListener { addPercentage() }
|
||||||
binding.cut.setOnClickListener { cutNumbers() }
|
binding.cut.setOnClickListener { cutNumbers() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,41 +101,57 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
currentExpression += number
|
currentExpression += number
|
||||||
}
|
}
|
||||||
lastWasOperator = false
|
lastWasOperator = false
|
||||||
|
lastWasPercent = false
|
||||||
updateDisplay()
|
updateDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupOperatorButton(button: MaterialButton, operator: String) {
|
private fun setupOperatorButton(button: MaterialButton, operator: String) {
|
||||||
button.setOnClickListener {
|
button.setOnClickListener {
|
||||||
if (!lastWasOperator) {
|
if (lastWasOperator) {
|
||||||
|
currentExpression = currentExpression.substring(0, currentExpression.length - 1) +
|
||||||
|
when (operator) {
|
||||||
|
"×" -> "*"
|
||||||
|
else -> operator
|
||||||
|
}
|
||||||
|
} else if (!lastWasPercent) {
|
||||||
currentExpression += when (operator) {
|
currentExpression += when (operator) {
|
||||||
"×" -> "*"
|
"×" -> "*"
|
||||||
else -> operator
|
else -> operator
|
||||||
}
|
}
|
||||||
lastWasOperator = true
|
lastWasOperator = true
|
||||||
|
lastWasPercent = false
|
||||||
hasDecimal = false
|
hasDecimal = false
|
||||||
}
|
}
|
||||||
updateDisplay()
|
updateDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun clearDisplay() {
|
private fun clearDisplay() {
|
||||||
currentExpression = "0"
|
currentExpression = "0"
|
||||||
binding.total.text = ""
|
binding.total.text = ""
|
||||||
lastWasOperator = false
|
lastWasOperator = false
|
||||||
|
lastWasPercent = false
|
||||||
hasDecimal = false
|
hasDecimal = false
|
||||||
updateDisplay()
|
updateDisplay()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addDecimal() {
|
private fun addDecimal() {
|
||||||
if (!hasDecimal && !lastWasOperator) {
|
if (!hasDecimal && !lastWasOperator && !lastWasPercent) {
|
||||||
currentExpression += "."
|
currentExpression += "."
|
||||||
hasDecimal = true
|
hasDecimal = true
|
||||||
updateDisplay()
|
updateDisplay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addPercentage() {
|
||||||
|
if (!lastWasOperator && !lastWasPercent) {
|
||||||
|
currentExpression += "%"
|
||||||
|
lastWasPercent = true
|
||||||
|
updateDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun calculatePercentage() {
|
private fun calculatePercentage() {
|
||||||
try {
|
try {
|
||||||
val value = currentExpression.toDouble()
|
val value = currentExpression.toDouble()
|
||||||
@@ -143,6 +162,126 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun preprocessExpression(expression: String): String {
|
||||||
|
val percentagePattern = Pattern.compile("(\\d+\\.?\\d*)%")
|
||||||
|
val operatorPercentPattern = Pattern.compile("([+\\-*/])(\\d+\\.?\\d*)%")
|
||||||
|
|
||||||
|
var processedExpression = expression
|
||||||
|
|
||||||
|
// Replace standalone percentages (like "50%") with their decimal form (0.5)
|
||||||
|
val matcher = percentagePattern.matcher(processedExpression)
|
||||||
|
while (matcher.find()) {
|
||||||
|
val fullMatch = matcher.group(0)
|
||||||
|
val number = matcher.group(1)
|
||||||
|
|
||||||
|
// Check if it's a standalone percentage or part of an operation
|
||||||
|
val start = matcher.start()
|
||||||
|
if (start == 0 || !isOperator(processedExpression[start-1].toString())) {
|
||||||
|
val percentageValue = number.toDouble() / 100
|
||||||
|
processedExpression = processedExpression.replace(fullMatch, percentageValue.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle operator-percentage combinations (like "100-20%")
|
||||||
|
val opMatcher = operatorPercentPattern.matcher(processedExpression)
|
||||||
|
val sb = StringBuilder(processedExpression)
|
||||||
|
|
||||||
|
// We need to process matches from right to left to maintain indices
|
||||||
|
val matches = mutableListOf<Triple<Int, Int, String>>()
|
||||||
|
|
||||||
|
while (opMatcher.find()) {
|
||||||
|
val operator = opMatcher.group(1)
|
||||||
|
val percentValue = opMatcher.group(2)!!.toDouble()
|
||||||
|
val start = opMatcher.start()
|
||||||
|
val end = opMatcher.end()
|
||||||
|
|
||||||
|
matches.add(Triple(start, end, "$operator$percentValue%"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process matches from right to left
|
||||||
|
for (match in matches.reversed()) {
|
||||||
|
val (start, end, fullMatch) = match
|
||||||
|
|
||||||
|
// Find the number before this operator
|
||||||
|
var leftNumberEnd = start
|
||||||
|
var leftNumberStart = start - 1
|
||||||
|
|
||||||
|
// Skip parentheses and move to the actual number
|
||||||
|
if (leftNumberStart >= 0 && sb[leftNumberStart] == ')') {
|
||||||
|
var openParens = 1
|
||||||
|
leftNumberStart--
|
||||||
|
|
||||||
|
while (leftNumberStart >= 0 && openParens > 0) {
|
||||||
|
if (sb[leftNumberStart] == ')') openParens++
|
||||||
|
else if (sb[leftNumberStart] == '(') openParens--
|
||||||
|
leftNumberStart--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we need to find the start of the expression
|
||||||
|
if (leftNumberStart >= 0) {
|
||||||
|
while (leftNumberStart >= 0 && (isDigit(sb[leftNumberStart].toString()) || sb[leftNumberStart] == '.' || sb[leftNumberStart] == '-')) {
|
||||||
|
leftNumberStart--
|
||||||
|
}
|
||||||
|
leftNumberStart++
|
||||||
|
} else {
|
||||||
|
leftNumberStart = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For simple numbers, just find the start of the number
|
||||||
|
while (leftNumberStart >= 0 && (isDigit(sb[leftNumberStart].toString()) || sb[leftNumberStart] == '.')) {
|
||||||
|
leftNumberStart--
|
||||||
|
}
|
||||||
|
leftNumberStart++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftNumberStart < leftNumberEnd) {
|
||||||
|
val leftPart = sb.substring(leftNumberStart, leftNumberEnd)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Extract the numerical values
|
||||||
|
val baseNumber = evaluateExpression(leftPart)
|
||||||
|
val operator = fullMatch.substring(0, 1)
|
||||||
|
val percentNumber = fullMatch.substring(1, fullMatch.length - 1).toDouble()
|
||||||
|
|
||||||
|
// Calculate the percentage of the base number
|
||||||
|
val percentValue = baseNumber * (percentNumber / 100)
|
||||||
|
|
||||||
|
// Calculate the new value based on the operator
|
||||||
|
val newValue = when (operator) {
|
||||||
|
"+" -> baseNumber + percentValue
|
||||||
|
"-" -> baseNumber - percentValue
|
||||||
|
"*" -> baseNumber * (percentNumber / 100)
|
||||||
|
"/" -> baseNumber / (percentNumber / 100)
|
||||||
|
else -> baseNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the entire expression "number operator percent%" with the result
|
||||||
|
sb.replace(leftNumberStart, end, newValue.toString())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("Calculator", "Error processing percentage expression: $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isOperator(char: String): Boolean {
|
||||||
|
return char == "+" || char == "-" || char == "*" || char == "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isDigit(char: String): Boolean {
|
||||||
|
return char.matches(Regex("[0-9]"))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evaluateExpression(expression: String): Double {
|
||||||
|
return try {
|
||||||
|
ExpressionBuilder(expression).build().evaluate()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
expression.toDouble()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun calculateResult() {
|
private fun calculateResult() {
|
||||||
if (currentExpression == "123456") {
|
if (currentExpression == "123456") {
|
||||||
val intent = Intent(this, SetupPasswordActivity::class.java)
|
val intent = Intent(this, SetupPasswordActivity::class.java)
|
||||||
@@ -161,8 +300,15 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
currentExpression = currentExpression.replace("×", "*")
|
// Replace '×' with '*' for the expression evaluator
|
||||||
val expression = ExpressionBuilder(currentExpression).build()
|
var processedExpression = currentExpression.replace("×", "*")
|
||||||
|
|
||||||
|
// Process percentages in the expression
|
||||||
|
if (processedExpression.contains("%")) {
|
||||||
|
processedExpression = preprocessExpression(processedExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
val expression = ExpressionBuilder(processedExpression).build()
|
||||||
val result = expression.evaluate()
|
val result = expression.evaluate()
|
||||||
|
|
||||||
currentExpression = if (result.toLong().toDouble() == result) {
|
currentExpression = if (result.toLong().toDouble() == result) {
|
||||||
@@ -172,16 +318,17 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastWasOperator = false
|
lastWasOperator = false
|
||||||
|
lastWasPercent = false
|
||||||
hasDecimal = currentExpression.contains(".")
|
hasDecimal = currentExpression.contains(".")
|
||||||
|
|
||||||
updateDisplay()
|
updateDisplay()
|
||||||
binding.total.text = ""
|
binding.total.text = ""
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
binding.display.text = getString(R.string.invalid_message)
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
private fun updateDisplay() {
|
private fun updateDisplay() {
|
||||||
binding.display.text = currentExpression.replace("*", "×")
|
binding.display.text = currentExpression.replace("*", "×")
|
||||||
|
|
||||||
@@ -191,8 +338,24 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val expression = ExpressionBuilder(currentExpression).build()
|
// Don't show preview result if the expression ends with an operator
|
||||||
|
// (but allow percentage at the end)
|
||||||
|
if (currentExpression.isEmpty() ||
|
||||||
|
(isOperator(currentExpression.last().toString()) && currentExpression.last() != '%')) {
|
||||||
|
binding.total.text = ""
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the expression for preview calculation
|
||||||
|
var processedExpression = currentExpression.replace("×", "*")
|
||||||
|
|
||||||
|
if (processedExpression.contains("%")) {
|
||||||
|
processedExpression = preprocessExpression(processedExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
val expression = ExpressionBuilder(processedExpression).build()
|
||||||
val result = expression.evaluate()
|
val result = expression.evaluate()
|
||||||
|
|
||||||
val formattedResult = if (result.toLong().toDouble() == result) {
|
val formattedResult = if (result.toLong().toDouble() == result) {
|
||||||
result.toLong().toString()
|
result.toLong().toString()
|
||||||
} else {
|
} else {
|
||||||
@@ -205,16 +368,27 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun cutNumbers() {
|
private fun cutNumbers() {
|
||||||
if (currentExpression.isNotEmpty()){
|
if (currentExpression.isNotEmpty()){
|
||||||
if (currentExpression.length == 1){
|
if (currentExpression.length == 1){
|
||||||
currentExpression = currentExpression.substring(0, currentExpression.length - 1)
|
|
||||||
currentExpression = "0"
|
currentExpression = "0"
|
||||||
}else currentExpression = currentExpression.substring(0, currentExpression.length - 1)
|
} else {
|
||||||
}else currentExpression = "0"
|
val lastChar = currentExpression.last()
|
||||||
updateDisplay()
|
currentExpression = currentExpression.substring(0, currentExpression.length - 1)
|
||||||
|
|
||||||
|
// Update flags based on what was removed
|
||||||
|
if (lastChar == '%') {
|
||||||
|
lastWasPercent = false
|
||||||
|
} else if (isOperator(lastChar.toString())) {
|
||||||
|
lastWasOperator = false
|
||||||
|
} else if (lastChar == '.') {
|
||||||
|
hasDecimal = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentExpression = "0"
|
||||||
|
}
|
||||||
|
updateDisplay()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPositiveButtonClicked() {
|
override fun onPositiveButtonClicked() {
|
||||||
@@ -240,5 +414,3 @@ class MainActivity : AppCompatActivity(), DialogActionsCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import android.net.Uri
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.viewpager.widget.ViewPager
|
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.adapters.ImagePreviewAdapter
|
import devs.org.calculator.adapters.ImagePreviewAdapter
|
||||||
import devs.org.calculator.callbacks.DialogActionsCallback
|
import devs.org.calculator.callbacks.DialogActionsCallback
|
||||||
import devs.org.calculator.databinding.ActivityPreviewBinding
|
import devs.org.calculator.databinding.ActivityPreviewBinding
|
||||||
@@ -13,7 +13,6 @@ import devs.org.calculator.utils.DialogUtil
|
|||||||
import devs.org.calculator.utils.FileManager
|
import devs.org.calculator.utils.FileManager
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import devs.org.calculator.R
|
|
||||||
|
|
||||||
class PreviewActivity : AppCompatActivity() {
|
class PreviewActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@@ -55,19 +54,19 @@ class PreviewActivity : AppCompatActivity() {
|
|||||||
when (type) {
|
when (type) {
|
||||||
"IMAGE" -> {
|
"IMAGE" -> {
|
||||||
filetype = FileManager.FileType.IMAGE
|
filetype = FileManager.FileType.IMAGE
|
||||||
binding.title.text = "Preview Images"
|
binding.title.text = getString(R.string.preview_images)
|
||||||
}
|
}
|
||||||
"VIDEO" -> {
|
"VIDEO" -> {
|
||||||
filetype = FileManager.FileType.VIDEO
|
filetype = FileManager.FileType.VIDEO
|
||||||
binding.title.text = "Preview Videos"
|
binding.title.text = getString(R.string.preview_videos)
|
||||||
}
|
}
|
||||||
"AUDIO" -> {
|
"AUDIO" -> {
|
||||||
filetype = FileManager.FileType.AUDIO
|
filetype = FileManager.FileType.AUDIO
|
||||||
binding.title.text = "Preview Audios"
|
binding.title.text = getString(R.string.preview_audios)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
filetype = FileManager.FileType.DOCUMENT
|
filetype = FileManager.FileType.DOCUMENT
|
||||||
binding.title.text = "Preview Documents"
|
binding.title.text = getString(R.string.preview_documents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,10 +106,10 @@ class PreviewActivity : AppCompatActivity() {
|
|||||||
val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype)
|
val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype)
|
||||||
if (fileUri != null) {
|
if (fileUri != null) {
|
||||||
dialogUtil.showMaterialDialog(
|
dialogUtil.showMaterialDialog(
|
||||||
"Delete File",
|
getString(R.string.delete_file),
|
||||||
"Are you sure to Delete this file permanently?",
|
getString(R.string.are_you_sure_to_delete_this_file_permanently),
|
||||||
"Delete Permanently",
|
getString(R.string.delete_permanently),
|
||||||
"Cancel",
|
getString(R.string.cancel),
|
||||||
object : DialogActionsCallback{
|
object : DialogActionsCallback{
|
||||||
override fun onPositiveButtonClicked() {
|
override fun onPositiveButtonClicked() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
@@ -136,10 +135,10 @@ class PreviewActivity : AppCompatActivity() {
|
|||||||
val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype)
|
val fileUri = FileManager.FileManager().getContentUriImage(this, files[binding.viewPager.currentItem], filetype)
|
||||||
if (fileUri != null) {
|
if (fileUri != null) {
|
||||||
dialogUtil.showMaterialDialog(
|
dialogUtil.showMaterialDialog(
|
||||||
"Unhide File",
|
getString(R.string.un_hide_file),
|
||||||
"Are you sure you want to Unhide this file?",
|
getString(R.string.are_you_sure_you_want_to_un_hide_this_file),
|
||||||
"Unhide",
|
getString(R.string.un_hide),
|
||||||
"Cancel",
|
getString(R.string.cancel),
|
||||||
object : DialogActionsCallback{
|
object : DialogActionsCallback{
|
||||||
override fun onPositiveButtonClicked() {
|
override fun onPositiveButtonClicked() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
@@ -168,7 +167,7 @@ class PreviewActivity : AppCompatActivity() {
|
|||||||
adapter.images = updatedFiles // Update adapter with the new list
|
adapter.images = updatedFiles // Update adapter with the new list
|
||||||
|
|
||||||
// Update the ViewPager's position
|
// Update the ViewPager's position
|
||||||
if (!updatedFiles.isNotEmpty()) finish()
|
if (updatedFiles.isEmpty()) finish()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,28 +45,28 @@ class SetupPasswordActivity : AppCompatActivity() {
|
|||||||
val securityAnswer = binding.etSecurityAnswer.text.toString()
|
val securityAnswer = binding.etSecurityAnswer.text.toString()
|
||||||
|
|
||||||
if (password.isEmpty()){
|
if (password.isEmpty()){
|
||||||
binding.etPassword.error = "Enter password"
|
binding.etPassword.error = getString(R.string.enter_password)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (confirmPassword.isEmpty()){
|
if (confirmPassword.isEmpty()){
|
||||||
binding.etConfirmPassword.error = "Confirm password"
|
binding.etConfirmPassword.error = getString(R.string.confirm_password)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (securityQuestion.isEmpty()){
|
if (securityQuestion.isEmpty()){
|
||||||
binding.etSecurityQuestion.error = "Enter security question"
|
binding.etSecurityQuestion.error = getString(R.string.enter_security_question)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (securityAnswer.isEmpty()){
|
if (securityAnswer.isEmpty()){
|
||||||
binding.etSecurityAnswer.error = "Enter security answer"
|
binding.etSecurityAnswer.error = getString(R.string.enter_security_answer)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (password != confirmPassword) {
|
if (password != confirmPassword) {
|
||||||
binding.etPassword.error = "Passwords don't match"
|
binding.etPassword.error = getString(R.string.passwords_don_t_match)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
prefsUtil.savePassword(password)
|
prefsUtil.savePassword(password)
|
||||||
prefsUtil.saveSecurityQA(securityQuestion, securityAnswer)
|
prefsUtil.saveSecurityQA(securityQuestion, securityAnswer)
|
||||||
Toast.makeText(this, "Password set successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.password_set_successfully), Toast.LENGTH_SHORT).show()
|
||||||
startActivity(Intent(this, MainActivity::class.java))
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
@@ -75,40 +75,43 @@ class SetupPasswordActivity : AppCompatActivity() {
|
|||||||
// Implement password reset logic
|
// Implement password reset logic
|
||||||
// Could use security questions or email verification
|
// Could use security questions or email verification
|
||||||
if (prefsUtil.getSecurityQuestion() != null) showSecurityQuestionDialog(prefsUtil.getSecurityQuestion().toString())
|
if (prefsUtil.getSecurityQuestion() != null) showSecurityQuestionDialog(prefsUtil.getSecurityQuestion().toString())
|
||||||
else Toast.makeText(this, "Security question not set yet.", Toast.LENGTH_SHORT).show()
|
else Toast.makeText(this,
|
||||||
|
getString(R.string.security_question_not_set_yet), Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
}
|
}
|
||||||
binding2.btnChangePassword.setOnClickListener{
|
binding2.btnChangePassword.setOnClickListener{
|
||||||
val oldPassword = binding2.etOldPassword.text.toString()
|
val oldPassword = binding2.etOldPassword.text.toString()
|
||||||
val newPassword = binding2.etNewPassword.text.toString()
|
val newPassword = binding2.etNewPassword.text.toString()
|
||||||
if (oldPassword.isEmpty()) {
|
if (oldPassword.isEmpty()) {
|
||||||
binding2.etOldPassword.error = "This field can't be empty"
|
binding2.etOldPassword.error = getString(R.string.this_field_can_t_be_empty)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (newPassword.isEmpty()) {
|
if (newPassword.isEmpty()) {
|
||||||
binding2.etNewPassword.error = "This field can't be empty"
|
binding2.etNewPassword.error = getString(R.string.this_field_can_t_be_empty)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefsUtil.validatePassword(oldPassword)){
|
if (prefsUtil.validatePassword(oldPassword)){
|
||||||
if (oldPassword != newPassword){
|
if (oldPassword != newPassword){
|
||||||
prefsUtil.savePassword(newPassword)
|
prefsUtil.savePassword(newPassword)
|
||||||
Toast.makeText(this, "Password reset successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this,
|
||||||
|
getString(R.string.password_reset_successfully), Toast.LENGTH_SHORT).show()
|
||||||
startActivity(Intent(this, MainActivity::class.java))
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
finish()
|
finish()
|
||||||
|
|
||||||
}else {
|
}else {
|
||||||
Toast.makeText(this, "Old Password And New Password Not Be Same", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this,
|
||||||
binding2.etNewPassword.error = "Old Password And New Password Not Be Same"
|
getString(R.string.old_password_and_new_password_not_be_same), Toast.LENGTH_SHORT).show()
|
||||||
|
binding2.etNewPassword.error = getString(R.string.old_password_and_new_password_not_be_same)
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
Toast.makeText(this, "Wrong password entered", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.wrong_password_entered), Toast.LENGTH_SHORT).show()
|
||||||
binding2.etOldPassword.error = "Old Password Not Matching"
|
binding2.etOldPassword.error = getString(R.string.old_password_not_matching)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding2.btnResetPassword.setOnClickListener{
|
binding2.btnResetPassword.setOnClickListener{
|
||||||
if (prefsUtil.getSecurityQuestion() != null) showSecurityQuestionDialog(prefsUtil.getSecurityQuestion().toString())
|
if (prefsUtil.getSecurityQuestion() != null) showSecurityQuestionDialog(prefsUtil.getSecurityQuestion().toString())
|
||||||
else Toast.makeText(this, "Security question not set yet.", Toast.LENGTH_SHORT).show()
|
else Toast.makeText(this, getString(R.string.this_field_can_t_be_empty), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,26 +123,28 @@ class SetupPasswordActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setTitle("Answer the Security Question!")
|
.setTitle(getString(R.string.answer_the_security_question))
|
||||||
.setView(dialogView)
|
.setView(dialogView)
|
||||||
.setPositiveButton("Verify") { dialog, _ ->
|
.setPositiveButton(getString(R.string.verify)) { dialog, _ ->
|
||||||
val inputEditText: TextInputEditText = dialogView.findViewById(R.id.text_input_edit_text)
|
val inputEditText: TextInputEditText = dialogView.findViewById(R.id.text_input_edit_text)
|
||||||
val userAnswer = inputEditText.text.toString().trim()
|
val userAnswer = inputEditText.text.toString().trim()
|
||||||
|
|
||||||
if (userAnswer.isEmpty()) {
|
if (userAnswer.isEmpty()) {
|
||||||
Toast.makeText(this, "Answer cannot be empty!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this,
|
||||||
|
getString(R.string.answer_cannot_be_empty), Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
if (prefsUtil.validateSecurityAnswer(userAnswer)){
|
if (prefsUtil.validateSecurityAnswer(userAnswer)){
|
||||||
prefsUtil.resetPassword()
|
prefsUtil.resetPassword()
|
||||||
Toast.makeText(this, "Password successfully reset.", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this,
|
||||||
|
getString(R.string.password_successfully_reset), Toast.LENGTH_SHORT).show()
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}else {
|
}else {
|
||||||
Toast.makeText(this, "Invalid answer!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.invalid_answer), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setNegativeButton("Cancel") { dialog, _ ->
|
.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
|
||||||
|
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.widget.Toast
|
|||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.utils.FileManager
|
import devs.org.calculator.utils.FileManager
|
||||||
import devs.org.calculator.callbacks.FileProcessCallback
|
import devs.org.calculator.callbacks.FileProcessCallback
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -15,7 +16,6 @@ import java.io.File
|
|||||||
class VideoGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
class VideoGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
||||||
override val fileType = FileManager.FileType.VIDEO
|
override val fileType = FileManager.FileType.VIDEO
|
||||||
private lateinit var pickLauncher: ActivityResultLauncher<Intent>
|
private lateinit var pickLauncher: ActivityResultLauncher<Intent>
|
||||||
private var selectedUri: Uri? = null
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -42,19 +42,21 @@ class VideoGalleryActivity : BaseGalleryActivity(), FileProcessCallback {
|
|||||||
.processMultipleFiles(uriList, fileType,this@VideoGalleryActivity )
|
.processMultipleFiles(uriList, fileType,this@VideoGalleryActivity )
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "No files selected", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.no_files_selected), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
override fun onFilesProcessedSuccessfully(copiedFiles: List<File>) {
|
||||||
Toast.makeText(this@VideoGalleryActivity, "${copiedFiles.size} Videos hidden successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@VideoGalleryActivity, "${copiedFiles.size} ${getString(R.string.videos_hidden_successfully)}"
|
||||||
|
, Toast.LENGTH_SHORT).show()
|
||||||
loadFiles()
|
loadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFileProcessFailed() {
|
override fun onFileProcessFailed() {
|
||||||
Toast.makeText(this@VideoGalleryActivity, "Failed to hide videos", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@VideoGalleryActivity,
|
||||||
|
getString(R.string.failed_to_hide_videos), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupFabButton() {
|
private fun setupFabButton() {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import androidx.recyclerview.widget.DiffUtil
|
|||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import devs.org.calculator.R
|
import devs.org.calculator.R
|
||||||
import devs.org.calculator.activities.PreviewActivity
|
import devs.org.calculator.activities.PreviewActivity
|
||||||
import devs.org.calculator.callbacks.DialogActionsCallback
|
import devs.org.calculator.callbacks.DialogActionsCallback
|
||||||
@@ -35,18 +34,18 @@ class FileAdapter(
|
|||||||
private var fileTypes = when (fileType) {
|
private var fileTypes = when (fileType) {
|
||||||
|
|
||||||
FileManager.FileType.IMAGE -> {
|
FileManager.FileType.IMAGE -> {
|
||||||
"IMAGE"
|
context.getString(R.string.image)
|
||||||
}
|
}
|
||||||
|
|
||||||
FileManager.FileType.VIDEO -> {
|
FileManager.FileType.VIDEO -> {
|
||||||
"VIDEO"
|
context.getString(R.string.video)
|
||||||
}
|
}
|
||||||
|
|
||||||
FileManager.FileType.AUDIO -> {
|
FileManager.FileType.AUDIO -> {
|
||||||
"AUDIO"
|
context.getString(R.string.audio)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> "DOCUMENT"
|
else -> context.getString(R.string.document)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +92,8 @@ class FileAdapter(
|
|||||||
try {
|
try {
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Toast.makeText(context, "No audio player found!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context,
|
||||||
|
context.getString(R.string.no_audio_player_found), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,8 @@ class FileAdapter(
|
|||||||
try {
|
try {
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Toast.makeText(context, "No suitable app found to open this document!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context,
|
||||||
|
context.getString(R.string.no_suitable_app_found_to_open_this_document), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -131,14 +132,14 @@ class FileAdapter(
|
|||||||
|
|
||||||
}
|
}
|
||||||
fileName = FileManager.FileName(context).getFileNameFromUri(fileUri)?.toString()
|
fileName = FileManager.FileName(context).getFileNameFromUri(fileUri)?.toString()
|
||||||
?: "Unknown File"
|
?: context.getString(R.string.unknown_file)
|
||||||
|
|
||||||
DialogUtil(context).showMaterialDialogWithNaturalButton(
|
DialogUtil(context).showMaterialDialogWithNaturalButton(
|
||||||
"$fileTypes DETAILS",
|
context.getString(R.string.details, fileTypes),
|
||||||
"File Name: $fileName\n\nFile Path: $file\n\nYou can permanently delete or unhide this file.",
|
"File Name: $fileName\n\nFile Path: $file\n\nYou can permanently delete or un-hide this file.",
|
||||||
"Delete Permanently",
|
context.getString(R.string.delete_permanently),
|
||||||
"Unhide",
|
context.getString(R.string.un_hide),
|
||||||
"Cancel",
|
context.getString(R.string.cancel),
|
||||||
object : DialogActionsCallback {
|
object : DialogActionsCallback {
|
||||||
override fun onPositiveButtonClicked() {
|
override fun onPositiveButtonClicked() {
|
||||||
lifecycleOwner.lifecycleScope.launch {
|
lifecycleOwner.lifecycleScope.launch {
|
||||||
|
|||||||
@@ -1,22 +1,10 @@
|
|||||||
package devs.org.calculator.utils
|
package devs.org.calculator.utils
|
||||||
|
|
||||||
import android.app.RecoverableSecurityException
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.IntentSenderRequest
|
import androidx.activity.result.IntentSenderRequest
|
||||||
import androidx.documentfile.provider.DocumentFile
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
import devs.org.calculator.R
|
|
||||||
import devs.org.calculator.callbacks.DialogActionsCallback
|
import devs.org.calculator.callbacks.DialogActionsCallback
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class DialogUtil(private val context: Context) {
|
class DialogUtil(private val context: Context) {
|
||||||
private lateinit var intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
|
private lateinit var intentSenderLauncher: ActivityResultLauncher<IntentSenderRequest>
|
||||||
@@ -57,7 +45,7 @@ class DialogUtil(private val context: Context) {
|
|||||||
MaterialAlertDialogBuilder(context)
|
MaterialAlertDialogBuilder(context)
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.setPositiveButton(positiveButton) { dialog, _ ->
|
.setPositiveButton(positiveButton) { _, _ ->
|
||||||
// Handle positive button click
|
// Handle positive button click
|
||||||
callback.onPositiveButtonClicked()
|
callback.onPositiveButtonClicked()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class FileManager(private val context: Context, private val lifecycleOwner: Life
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyFileToHiddenDir(uri: Uri, type: FileType): File? {
|
private fun copyFileToHiddenDir(uri: Uri, type: FileType): File? {
|
||||||
return try {
|
return try {
|
||||||
val contentResolver = context.contentResolver
|
val contentResolver = context.contentResolver
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ class FileManager(private val context: Context, private val lifecycleOwner: Life
|
|||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
context,
|
context,
|
||||||
"Error hiding/unhiding file: ${e.message}",
|
"Error hiding/un-hiding file: ${e.message}",
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,20 +8,41 @@
|
|||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
|
android:visibility="gone"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="8dp" />
|
android:padding="8dp" />
|
||||||
|
|
||||||
<!-- <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton-->
|
<LinearLayout
|
||||||
<!-- android:id="@+id/fabAdd"-->
|
android:id="@+id/loading"
|
||||||
<!-- android:layout_width="wrap_content"-->
|
android:layout_width="match_parent"
|
||||||
<!-- android:layout_height="wrap_content"-->
|
android:layout_height="match_parent"
|
||||||
<!-- android:layout_gravity="bottom|end"-->
|
android:layout_gravity="center"
|
||||||
<!-- android:layout_margin="16dp"-->
|
android:visibility="visible"
|
||||||
<!-- android:contentDescription="Compose"-->
|
android:gravity="center"
|
||||||
<!-- android:icon="@drawable/plus"-->
|
android:orientation="vertical">
|
||||||
<!-- android:text="Add File"-->
|
<ProgressBar
|
||||||
<!-- app:elevation="6dp"/>-->
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/noItems"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/noItemsTxt"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="25dp"
|
||||||
|
android:text="@string/no_items_available_add_one_by_clicking_on_the_plus_button"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
android:id="@+id/fabAdd"
|
android:id="@+id/fabAdd"
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="8dp" />
|
android:padding="8dp" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/fabAdd"
|
android:id="@+id/fabAdd"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
|
|||||||
@@ -1,319 +1,329 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/main"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".activities.MainActivity">
|
tools:context=".activities.MainActivity">
|
||||||
|
|
||||||
<!-- Calculator Display -->
|
<!-- Calculator Display -->
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/displayContainer"
|
||||||
android:layout_height="160dp"
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
android:layout_weight="3"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:layout_marginTop="0dp"
|
app:layout_constraintHeight_percent="0.3"
|
||||||
android:orientation="vertical"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:gravity="right|bottom">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
<TextView
|
|
||||||
android:id="@+id/display"
|
<LinearLayout
|
||||||
|
android:id="@+id/scrollView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
|
android:scrollbars="none"
|
||||||
android:gravity="end|bottom"
|
android:gravity="end|bottom"
|
||||||
android:padding="10dp"
|
app:layout_constraintBottom_toTopOf="@+id/total"
|
||||||
android:text="0"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:textSize="48sp"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:autoSizeTextType="uniform"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:autoSizeMinTextSize="20sp"
|
app:layout_constraintVertical_chainStyle="packed">
|
||||||
android:autoSizeMaxTextSize="48sp"
|
|
||||||
android:autoSizeStepGranularity="2sp"
|
<LinearLayout
|
||||||
tools:ignore="Suspicious0dp" />
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:gravity="end|bottom"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/display"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoSizeMaxTextSize="48sp"
|
||||||
|
android:autoSizeMinTextSize="16sp"
|
||||||
|
android:autoSizeStepGranularity="2sp"
|
||||||
|
android:gravity="end|bottom"
|
||||||
|
android:autoSizeTextType="uniform"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="0"
|
||||||
|
android:textSize="48sp"
|
||||||
|
tools:ignore="Suspicious0dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/total"
|
android:id="@+id/total"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:autoSizeMaxTextSize="26sp"
|
||||||
|
android:autoSizeMinTextSize="24sp"
|
||||||
|
android:autoSizeStepGranularity="2sp"
|
||||||
|
android:autoSizeTextType="uniform"
|
||||||
android:gravity="end|bottom"
|
android:gravity="end|bottom"
|
||||||
android:paddingRight="10dp"
|
android:paddingRight="10dp"
|
||||||
android:paddingBottom="10dp"
|
android:paddingBottom="10dp"
|
||||||
android:text=""
|
android:text=""
|
||||||
android:textSize="26sp"
|
android:textSize="26sp"
|
||||||
android:autoSizeTextType="uniform"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:autoSizeMinTextSize="20sp"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:autoSizeMaxTextSize="48sp"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:autoSizeStepGranularity="2sp"
|
app:layout_constraintTop_toBottomOf="@+id/scrollView"
|
||||||
tools:ignore="Suspicious0dp" />
|
tools:ignore="Suspicious0dp" />
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Calculator Buttons -->
|
<!-- Calculator Buttons -->
|
||||||
<GridLayout
|
<androidx.gridlayout.widget.GridLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/buttonGrid"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:columnCount="4"
|
app:columnCount="4"
|
||||||
android:layout_weight="4"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:rowCount="5">
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/displayContainer"
|
||||||
|
app:rowCount="5">
|
||||||
|
|
||||||
<!-- Row 1 -->
|
<!-- Row 1 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnClear"
|
android:id="@+id/btnClear"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="C"
|
android:text="C"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_columnWeight="1"
|
||||||
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnPercent"
|
android:id="@+id/btnPercent"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="%"
|
android:text="%"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnDivide"
|
android:id="@+id/btnDivide"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="÷"
|
android:text="÷"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/cut"
|
android:id="@+id/cut"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_width="70dp"
|
android:layout_height="0dp"
|
||||||
android:layout_rowWeight="1"
|
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
app:icon="@drawable/backspace"
|
android:gravity="center"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
android:textSize="30sp"
|
||||||
|
app:cornerRadius="15dp"
|
||||||
|
app:icon="@drawable/backspace"
|
||||||
app:iconSize="32dp"
|
app:iconSize="32dp"
|
||||||
app:cornerRadius="15dp"/>
|
app:layout_columnWeight="1"
|
||||||
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<!-- Row 2 -->
|
<!-- Row 2 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn7"
|
android:id="@+id/btn7"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="7"
|
android:text="7"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_columnWeight="1"
|
||||||
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn8"
|
android:id="@+id/btn8"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="8"
|
android:text="8"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_columnWeight="1"
|
||||||
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn9"
|
android:id="@+id/btn9"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="9"
|
android:text="9"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnMultiply"
|
android:id="@+id/btnMultiply"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:textSize="30sp"
|
|
||||||
android:text="×"
|
android:text="×"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<!-- Row 3 -->
|
<!-- Row 3 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn4"
|
android:id="@+id/btn4"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
app:cornerRadius="15dp"
|
|
||||||
android:text="4"
|
android:text="4"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
android:textSize="30sp"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:cornerRadius="15dp"
|
||||||
|
app:layout_columnWeight="1"
|
||||||
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn5"
|
android:id="@+id/btn5"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="5"
|
android:text="5"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn6"
|
android:id="@+id/btn6"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="6"
|
android:text="6"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnMinus"
|
android:id="@+id/btnMinus"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="-"
|
android:text="-"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<!-- Row 4 -->
|
<!-- Row 4 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn1"
|
android:id="@+id/btn1"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="1"
|
android:text="1"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn2"
|
android:id="@+id/btn2"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="2"
|
android:text="2"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn3"
|
android:id="@+id/btn3"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="3"
|
android:text="3"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnPlus"
|
android:id="@+id/btnPlus"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="+"
|
android:text="+"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<!-- Row 5 -->
|
<!-- Row 5 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn0"
|
android:id="@+id/btn0"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_width="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="70dp"
|
android:layout_height="0dp"
|
||||||
android:layout_rowWeight="1"
|
|
||||||
android:layout_columnSpan="2"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_columnWeight="2"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
|
android:text="0"
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnSpan="2"
|
||||||
android:text="0" />
|
app:layout_columnWeight="2"
|
||||||
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnDot"
|
android:id="@+id/btnDot"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="."
|
android:text="."
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnEquals"
|
android:id="@+id/btnEquals"
|
||||||
android:layout_width="70dp"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
android:layout_height="70dp"
|
android:layout_width="0dp"
|
||||||
android:layout_rowWeight="1"
|
android:layout_height="0dp"
|
||||||
android:textSize="30sp"
|
|
||||||
android:layout_columnWeight="1"
|
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:text="="
|
android:text="="
|
||||||
|
android:textSize="30sp"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_columnWeight="1"
|
||||||
style="@style/Widget.MaterialComponents.Button"/>
|
app:layout_rowWeight="1" />
|
||||||
|
|
||||||
</GridLayout>
|
</androidx.gridlayout.widget.GridLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -1,4 +1,56 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Calculator</string>
|
<string name="app_name">Calculator</string>
|
||||||
<string name="invalid_message">Invalid Value Entered</string>
|
<string name="invalid_message">Invalid Value Entered</string>
|
||||||
|
<string name="add_image">Add Image</string>
|
||||||
|
<string name="add_audio">Add Audio</string>
|
||||||
|
<string name="add_video">Add Video</string>
|
||||||
|
<string name="add_files">Add Files</string>
|
||||||
|
<string name="failed_to_hide_documents">Failed to hide Documents</string>
|
||||||
|
<string name="no_files_selected">No files selected</string>
|
||||||
|
<string name="documents_hidden_successfully"> Documents hidden successfully</string>
|
||||||
|
<string name="failed_to_hide_unhide_photo">Failed to hide/unhide photo</string>
|
||||||
|
<string name="images_hidden_successfully"> Images hidden successfully</string>
|
||||||
|
<string name="failed_to_hide_images">Failed to hide images</string>
|
||||||
|
<string name="storage_permissions_granted">Storage permissions granted</string>
|
||||||
|
<string name="storage_permissions_denied">Storage permissions denied</string>
|
||||||
|
<string name="preview_images">Preview Images</string>
|
||||||
|
<string name="preview_videos">Preview Videos</string>
|
||||||
|
<string name="preview_audios">Preview Audios</string>
|
||||||
|
<string name="preview_documents">Preview Documents</string>
|
||||||
|
<string name="delete_file">Delete File</string>
|
||||||
|
<string name="are_you_sure_to_delete_this_file_permanently">Are you sure to Delete this file permanently?</string>
|
||||||
|
<string name="delete_permanently">Delete Permanently</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
<string name="un_hide_file">Un-hide File</string>
|
||||||
|
<string name="are_you_sure_you_want_to_un_hide_this_file">Are you sure you want to Un-hide this file?</string>
|
||||||
|
<string name="un_hide">Un-hide</string>
|
||||||
|
<string name="enter_password">Enter password</string>
|
||||||
|
<string name="confirm_password">Confirm password</string>
|
||||||
|
<string name="enter_security_question">Enter security question</string>
|
||||||
|
<string name="enter_security_answer">Enter security answer</string>
|
||||||
|
<string name="passwords_don_t_match">Passwords don\'t match</string>
|
||||||
|
<string name="password_set_successfully">Password set successfully</string>
|
||||||
|
<string name="security_question_not_set_yet">Security question not set yet.</string>
|
||||||
|
<string name="this_field_can_t_be_empty">This field can\'t be empty</string>
|
||||||
|
<string name="password_reset_successfully">Password reset successfully</string>
|
||||||
|
<string name="old_password_and_new_password_not_be_same">Old Password And New Password Not Be Same</string>
|
||||||
|
<string name="wrong_password_entered">Wrong password entered</string>
|
||||||
|
<string name="old_password_not_matching">Old Password Not Matching</string>
|
||||||
|
<string name="answer_the_security_question">Answer the Security Question!</string>
|
||||||
|
<string name="verify">Verify</string>
|
||||||
|
<string name="answer_cannot_be_empty">Answer cannot be empty!</string>
|
||||||
|
<string name="password_successfully_reset">Password successfully reset.</string>
|
||||||
|
<string name="invalid_answer">Invalid answer!</string>
|
||||||
|
<string name="videos_hidden_successfully"> Videos hidden successfully</string>
|
||||||
|
<string name="failed_to_hide_videos">Failed to hide videos</string>
|
||||||
|
<string name="image">IMAGE</string>
|
||||||
|
<string name="video">VIDEO</string>
|
||||||
|
<string name="audio">AUDIO</string>
|
||||||
|
<string name="document">DOCUMENT</string>
|
||||||
|
<string name="no_audio_player_found">No audio player found!</string>
|
||||||
|
<string name="no_suitable_app_found_to_open_this_document">No suitable app found to open this document!</string>
|
||||||
|
<string name="unknown_file">Unknown File</string>
|
||||||
|
<string name="details"> DETAILS</string>
|
||||||
|
<string name="audio_hidded_successfully">Audios hidden successfully</string>
|
||||||
|
<string name="no_items_available_add_one_by_clicking_on_the_plus_button">No Items Available, Add one by clicking on the</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.7.2"
|
agp = "8.9.1"
|
||||||
|
documentfile = "1.0.1"
|
||||||
exp4j = "0.4.8"
|
exp4j = "0.4.8"
|
||||||
|
glide = "4.16.0"
|
||||||
kotlin = "1.9.24"
|
kotlin = "1.9.24"
|
||||||
coreKtx = "1.15.0"
|
coreKtx = "1.15.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
@@ -11,10 +13,17 @@ material = "1.12.0"
|
|||||||
activity = "1.9.3"
|
activity = "1.9.3"
|
||||||
constraintlayout = "2.2.0"
|
constraintlayout = "2.2.0"
|
||||||
materialColorUtilities = "1.3.0"
|
materialColorUtilities = "1.3.0"
|
||||||
|
gridlayout = "1.0.0"
|
||||||
|
photoview = "2.3.0"
|
||||||
|
viewpager = "1.1.0"
|
||||||
|
zoomage = "1.3.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "documentfile" }
|
||||||
|
androidx-viewpager = { module = "androidx.viewpager:viewpager", version.ref = "viewpager" }
|
||||||
exp4j = { module = "net.objecthunter:exp4j", version.ref = "exp4j" }
|
exp4j = { module = "net.objecthunter:exp4j", version.ref = "exp4j" }
|
||||||
|
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
@@ -23,6 +32,9 @@ material = { group = "com.google.android.material", name = "material", version.r
|
|||||||
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||||
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
material-color-utilities = { module = "com.google.android.material:material-color-utilities", version.ref = "materialColorUtilities" }
|
material-color-utilities = { module = "com.google.android.material:material-color-utilities", version.ref = "materialColorUtilities" }
|
||||||
|
androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" }
|
||||||
|
photoview = { module = "com.github.chrisbanes:PhotoView", version.ref = "photoview" }
|
||||||
|
zoomage = { module = "com.jsibbold:zoomage", version.ref = "zoomage" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Sun Nov 03 19:53:13 IST 2024
|
#Sun Nov 03 19:53:13 IST 2024
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Reference in New Issue
Block a user