mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-04-28 06:19:49 +00:00
3.4.0
- Added auto return to Home after importing rom and creating virtual machine in Rom store. - Improved image viewer. - Fixed Unknow display error in architecture in rom info if it is PowerPC architecture. - New setup wizard interface that automatically changes according to screen size. - New ID generator for virtual machine. - Added dialog when deleting virtual machine.
This commit is contained in:
parent
009ba90694
commit
bf11a28d60
25 changed files with 817 additions and 89 deletions
19
.gitignore
vendored
19
.gitignore
vendored
|
|
@ -37,17 +37,18 @@ captures/
|
|||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/gradle.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
.idea/libraries
|
||||
.idea/
|
||||
#.idea/workspace.xml
|
||||
#.idea/tasks.xml
|
||||
#.idea/gradle.xml
|
||||
#.idea/assetWizardSettings.xml
|
||||
#.idea/dictionaries
|
||||
#.idea/libraries
|
||||
# Android Studio 3 in .gitignore file.
|
||||
.idea/caches
|
||||
.idea/modules.xml
|
||||
#.idea/caches
|
||||
#.idea/modules.xml
|
||||
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||
.idea/navEditor.xml
|
||||
#.idea/navEditor.xml
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
|
|
|
|||
4
.idea/deploymentTargetSelector.xml
generated
4
.idea/deploymentTargetSelector.xml
generated
|
|
@ -4,10 +4,10 @@
|
|||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-11-29T08:52:45.170485500Z">
|
||||
<DropdownSelection timestamp="2025-11-30T05:38:16.444348800Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=8c847fb6" />
|
||||
<DeviceId pluginId="Default" identifier="serial=192.168.1.173:46503;connection=00a6f494" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ Help support the project by contributing!
|
|||
- [PROOT](https://proot-me.github.io/)
|
||||
- [QEMU](https://github.com/qemu/qemu)
|
||||
- [Termux](https://github.com/termux)
|
||||
- [ZoomImageView](https://github.com/k1slay/ZoomImageView)
|
||||
|
||||
[ico-telegram]: https://img.shields.io/badge/Telegram-2CA5E0?logo=telegram&logoColor=white
|
||||
[ico-discord]: https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
@ -10,8 +13,8 @@ android {
|
|||
applicationId "com.vectras.vm"
|
||||
minSdk minApi
|
||||
targetSdk targetApi
|
||||
versionCode 43
|
||||
versionName "3.3.9"
|
||||
versionCode 44
|
||||
versionName "3.4.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
|
@ -65,8 +68,15 @@ android {
|
|||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
buildToolsVersion '36.1.0'
|
||||
ndkVersion '21'
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_21)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
@ -74,9 +84,9 @@ dependencies {
|
|||
implementation 'androidx.appcompat:appcompat:1.7.1'
|
||||
implementation 'com.google.android.material:material:1.14.0-alpha07'
|
||||
implementation "androidx.annotation:annotation:1.9.1"
|
||||
implementation "androidx.core:core:1.17.0"
|
||||
implementation "androidx.core:core-ktx:1.17.0"
|
||||
implementation "androidx.drawerlayout:drawerlayout:1.2.0"
|
||||
implementation "androidx.preference:preference:1.2.1"
|
||||
implementation "androidx.preference:preference-ktx:1.2.1"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-rc01"
|
||||
implementation "androidx.viewpager:viewpager:1.1.0"
|
||||
// implementation platform('com.google.firebase:firebase-bom:34.2.0')
|
||||
|
|
@ -95,10 +105,11 @@ dependencies {
|
|||
implementation 'com.airbnb.android:lottie:6.7.1'
|
||||
implementation 'org.apache.commons:commons-compress:1.28.0'
|
||||
// implementation 'com.google.firebase:firebase-crashlytics-buildtools:3.0.6'
|
||||
implementation 'androidx.activity:activity:1.12.0'
|
||||
implementation 'androidx.activity:activity-ktx:1.12.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation "androidx.documentfile:documentfile:1.1.0"
|
||||
implementation 'androidx.core:core-ktx:1.17.0'
|
||||
compileOnly project(':shell-loader:stub')
|
||||
implementation project(":terminal-view")
|
||||
implementation project(":library")
|
||||
|
|
|
|||
445
app/src/main/java/com/k2/zoomimageview/ZoomImageView.kt
Normal file
445
app/src/main/java/com/k2/zoomimageview/ZoomImageView.kt
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
package com.k2.zoomimageview
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
import android.view.ScaleGestureDetector
|
||||
import android.view.ViewConfiguration
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.widget.OverScroller
|
||||
import androidx.core.animation.doOnCancel
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.view.ViewCompat
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
/**
|
||||
* @author Kislay [k.two.apps@gmail.com]
|
||||
* @since 03/09/20
|
||||
*/
|
||||
|
||||
class ZoomImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
|
||||
private val textPaint = Paint()
|
||||
private val zoomMatrix = Matrix()
|
||||
private val baseMatrix = Matrix()
|
||||
private val preEventImgRect = RectF()
|
||||
private val matrixValues = FloatArray(9)
|
||||
private val zoomInterpolator = AccelerateDecelerateInterpolator()
|
||||
private var logText = ""
|
||||
private var handlingDismiss = false
|
||||
private var touchSlop: Float = 0F
|
||||
private var oldScale = MIN_SCALE
|
||||
private var panAnimator: ValueAnimator? = null
|
||||
private var zoomAnimator: ValueAnimator? = null
|
||||
private var onClickListener: OnClickListener? = null
|
||||
private var onLongClickListener: OnLongClickListener? = null
|
||||
private var viewWidth = right - left - paddingLeft - paddingRight
|
||||
private var viewHeight = bottom - top - paddingTop - paddingBottom
|
||||
private lateinit var scroller: OverScroller
|
||||
private lateinit var tapDetector: GestureDetector
|
||||
private lateinit var scaleDetector: ScaleGestureDetector
|
||||
var debugInfoVisible = false
|
||||
var swipeToDismissEnabled = false
|
||||
var disallowPagingWhenZoomed = false
|
||||
var onDismiss: () -> Unit = {}
|
||||
var onDrawableLoaded: () -> Unit = {}
|
||||
var dismissProgressListener: (progress: Float) -> Unit = {}
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
initView()
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
initView()
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
|
||||
context, attrs, defStyleAttr
|
||||
) {
|
||||
initView()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
touchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
|
||||
initTextPaint()
|
||||
scaleType = ScaleType.MATRIX
|
||||
scaleDetector = ScaleGestureDetector(context, scaleListener)
|
||||
scroller = OverScroller(context, DecelerateInterpolator())
|
||||
tapDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onDoubleTap(e: MotionEvent): Boolean {
|
||||
oldScale = currentScale
|
||||
val scaleFactor = if (currentScale != MIN_SCALE) MIN_SCALE else MID_SCALE
|
||||
setScaleAbsolute(scaleFactor, e.x, e.y)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
||||
onClickListener?.onClick(this@ZoomImageView)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onLongPress(e: MotionEvent) {
|
||||
onLongClickListener?.onLongClick(this@ZoomImageView)
|
||||
}
|
||||
|
||||
override fun onScroll(
|
||||
e1: MotionEvent?,
|
||||
e2: MotionEvent,
|
||||
distanceX: Float,
|
||||
distanceY: Float
|
||||
): Boolean {
|
||||
if (scaleDetector.isInProgress) return false
|
||||
val xAbs = distanceX.absoluteValue
|
||||
val yAbs = distanceY.absoluteValue
|
||||
if (currentScale <= MIN_SCALE) {
|
||||
if (swipeToDismissEnabled && yAbs > xAbs) {
|
||||
handlingDismiss = true
|
||||
panImage(0F, distanceY)
|
||||
dismissProgressListener.invoke(dismissProgress)
|
||||
}
|
||||
} else {
|
||||
panImage(distanceX, distanceY)
|
||||
}
|
||||
var disallowParentIntercept = true
|
||||
if (!disallowPagingWhenZoomed) {
|
||||
if (handlingDismiss) {
|
||||
disallowParentIntercept = true
|
||||
} else if (xAbs > yAbs) {
|
||||
// horizontal scroll
|
||||
if (distanceX > 0F && preEventImgRect.right == viewWidth.toFloat())
|
||||
disallowParentIntercept = false
|
||||
else if (distanceX < 0F && preEventImgRect.left == 0F)
|
||||
disallowParentIntercept = false
|
||||
} else {
|
||||
// vertical scroll
|
||||
if (distanceY > 0F && preEventImgRect.bottom == viewHeight.toFloat())
|
||||
disallowParentIntercept = false
|
||||
else if (distanceY < 0F && preEventImgRect.top == 0F)
|
||||
disallowParentIntercept = false
|
||||
}
|
||||
}
|
||||
parent?.requestDisallowInterceptTouchEvent(disallowParentIntercept)
|
||||
return (xAbs > touchSlop || yAbs > touchSlop)
|
||||
}
|
||||
|
||||
override fun onFling(
|
||||
e1: MotionEvent?,
|
||||
e2: MotionEvent,
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean {
|
||||
if (currentZoom <= MIN_SCALE) return false
|
||||
val maxX = (preEventImgRect.width() - viewWidth).toInt()
|
||||
val maxY = (preEventImgRect.height() - viewHeight).toInt()
|
||||
flingRunnable.lastX = -preEventImgRect.left
|
||||
flingRunnable.lastY = -preEventImgRect.top
|
||||
scroller.fling(
|
||||
flingRunnable.lastX.toInt(), flingRunnable.lastY.toInt(), -velocityX.toInt(),
|
||||
-velocityY.toInt(), 0, maxX, 0, maxY
|
||||
)
|
||||
ViewCompat.postOnAnimation(this@ZoomImageView, flingRunnable)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDown(e: MotionEvent): Boolean {
|
||||
removeCallbacks(flingRunnable)
|
||||
scroller.forceFinished(true)
|
||||
displayRect?.let {
|
||||
preEventImgRect.set(it)
|
||||
}
|
||||
panAnimator?.removeAllUpdateListeners()
|
||||
panAnimator?.cancel()
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private val flingRunnable = object : Runnable {
|
||||
var lastX = 0F
|
||||
var lastY = 0F
|
||||
override fun run() {
|
||||
if (!scroller.isFinished && scroller.computeScrollOffset()) {
|
||||
val curX = scroller.currX.toFloat()
|
||||
val curY = scroller.currY.toFloat()
|
||||
panImage((curX - lastX), (curY - lastY))
|
||||
lastX = curX
|
||||
lastY = curY
|
||||
ViewCompat.postOnAnimation(this@ZoomImageView, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
val disallowIntercept =
|
||||
currentScale > MIN_SCALE || scaleDetector.isInProgress || handlingDismiss
|
||||
if (event.action == MotionEvent.ACTION_UP) {
|
||||
if (handlingDismiss) {
|
||||
if (currentTransY.absoluteValue > dismissThreshold) {
|
||||
onDismiss.invoke()
|
||||
} else {
|
||||
animatePan(0F, currentTransY, 0F, 0F, dismissProgress)
|
||||
}
|
||||
}
|
||||
}
|
||||
parent?.requestDisallowInterceptTouchEvent(disallowIntercept)
|
||||
return tapDetector.onTouchEvent(event) || return scaleDetector.onTouchEvent(event) || return true
|
||||
}
|
||||
|
||||
private fun setZoom(scale: Float, x: Float, y: Float) {
|
||||
zoomMatrix.postScale(scale, scale, x, y)
|
||||
setBounds()
|
||||
updateMatrix(drawMatrix)
|
||||
}
|
||||
|
||||
private fun updateMatrix(drawMatrix: Matrix) {
|
||||
logText = "tX: $currentTransX tY: $currentTransY"
|
||||
logText += " Scale: $currentScale"
|
||||
imageMatrix = drawMatrix
|
||||
}
|
||||
|
||||
private fun setScale(scale: Float, x: Float, y: Float) {
|
||||
setZoom(scale, x, y)
|
||||
}
|
||||
|
||||
private fun setScaleAbsolute(scale: Float, x: Float, y: Float) {
|
||||
val zoom = when {
|
||||
scale > MAX_SCALE -> MAX_SCALE
|
||||
scale < MIN_SCALE -> MIN_SCALE
|
||||
else -> scale
|
||||
}
|
||||
cancelAnimation()
|
||||
animateZoom(oldScale, zoom, x, y)
|
||||
}
|
||||
|
||||
private inline val drawableWidth: Int
|
||||
get() = drawable?.intrinsicWidth ?: 0
|
||||
|
||||
private inline val drawableHeight: Int
|
||||
get() = drawable?.intrinsicHeight ?: 0
|
||||
|
||||
override fun setImageDrawable(drawable: Drawable?) {
|
||||
super.setImageDrawable(drawable)
|
||||
if (drawable != null) {
|
||||
onDrawableLoaded.invoke()
|
||||
resetZoom()
|
||||
zoomMatrix.set(imageMatrix)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
viewWidth = right - left - paddingLeft - paddingRight
|
||||
viewHeight = bottom - top - paddingTop - paddingBottom
|
||||
if (changed) resetZoom()
|
||||
}
|
||||
|
||||
fun resetZoom() {
|
||||
val tempSrc = RectF(0F, 0F, drawableWidth.toFloat(), drawableHeight.toFloat())
|
||||
val tempDst = RectF(0F, 0F, viewWidth.toFloat(), viewHeight.toFloat())
|
||||
baseMatrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
|
||||
setScaleAbsolute(MIN_SCALE, viewWidth / 2F, viewHeight / 2F)
|
||||
imageMatrix = baseMatrix
|
||||
}
|
||||
|
||||
private val scaleListener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||
|
||||
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
||||
if (detector.scaleFactor.isNaN() || detector.scaleFactor.isInfinite())
|
||||
return false
|
||||
if (currentScale > MAX_SCALE && detector.scaleFactor > 1F)
|
||||
return false
|
||||
oldScale = currentScale
|
||||
setScale(detector.scaleFactor, detector.focusX, detector.focusY)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onScaleEnd(detector: ScaleGestureDetector) {
|
||||
super.onScaleEnd(detector)
|
||||
oldScale = currentScale
|
||||
var needsReset = false
|
||||
var newScale = MIN_SCALE
|
||||
if (currentScale < MIN_SCALE) {
|
||||
newScale = MIN_SCALE
|
||||
needsReset = true
|
||||
}
|
||||
if (needsReset) setScaleAbsolute(newScale, detector.focusX, detector.focusY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
if (debugInfoVisible) {
|
||||
canvas.drawText(logText, 10F, height - 10F, textPaint)
|
||||
val drawableBound = displayRect?.let {
|
||||
"Drawable: $it"
|
||||
} ?: ""
|
||||
canvas.drawText(drawableBound, 10F, 40F, textPaint)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initTextPaint() {
|
||||
textPaint.color = Color.WHITE
|
||||
textPaint.style = Paint.Style.FILL
|
||||
textPaint.textSize = 40F
|
||||
}
|
||||
|
||||
private fun animateZoom(startZoom: Float, endZoom: Float, x: Float, y: Float) {
|
||||
zoomAnimator = ValueAnimator.ofFloat(startZoom, endZoom).apply {
|
||||
duration = VALUE_ANIMATOR_DURATION
|
||||
addUpdateListener {
|
||||
val scale = (it.animatedValue as Float) / currentScale
|
||||
setZoom(scale, x, y)
|
||||
}
|
||||
interpolator = zoomInterpolator
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun animatePan(
|
||||
startX: Float, startY: Float, endX: Float, endY: Float, dismissProgress: Float? = null
|
||||
) {
|
||||
panAnimator = ValueAnimator.ofFloat(startX, startY, endX, endY).apply {
|
||||
duration = VALUE_ANIMATOR_DURATION
|
||||
addUpdateListener {
|
||||
val newX = (startX - endX) * it.animatedFraction
|
||||
val newY = (startY - endY) * it.animatedFraction
|
||||
panImage(startX - newX, startY - newY, setAbsolute = true)
|
||||
dismissProgress?.let { progress ->
|
||||
if (1.0F - it.animatedFraction < progress) {
|
||||
dismissProgressListener.invoke(1.0F - it.animatedFraction)
|
||||
}
|
||||
}
|
||||
}
|
||||
interpolator = zoomInterpolator
|
||||
start()
|
||||
doOnCancel {
|
||||
panImage(0F, 0F, setAbsolute = true)
|
||||
handlingDismiss = false
|
||||
}
|
||||
doOnEnd {
|
||||
handlingDismiss = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancelAnimation() {
|
||||
zoomAnimator?.removeAllUpdateListeners()
|
||||
zoomAnimator?.cancel()
|
||||
}
|
||||
|
||||
private fun panImage(x: Float, y: Float, setAbsolute: Boolean = false) {
|
||||
if (setAbsolute)
|
||||
zoomMatrix.setTranslate(x, y)
|
||||
else
|
||||
zoomMatrix.postTranslate(-x, -y)
|
||||
setBounds()
|
||||
updateMatrix(drawMatrix)
|
||||
}
|
||||
|
||||
private fun setBounds() {
|
||||
val rect = displayRect ?: return
|
||||
val height = rect.height()
|
||||
val width = rect.width()
|
||||
val viewHeight: Int = this.viewHeight
|
||||
var deltaX = 0f
|
||||
var deltaY = 0f
|
||||
when {
|
||||
height <= viewHeight -> {
|
||||
if (!handlingDismiss)
|
||||
deltaY = (viewHeight - height) / 2 - rect.top
|
||||
}
|
||||
rect.top > 0 -> {
|
||||
deltaY = -rect.top
|
||||
}
|
||||
rect.bottom < viewHeight -> {
|
||||
deltaY = viewHeight - rect.bottom
|
||||
}
|
||||
}
|
||||
val viewWidth: Int = this.viewWidth
|
||||
when {
|
||||
width <= viewWidth -> {
|
||||
deltaX = (viewWidth - width) / 2 - rect.left
|
||||
}
|
||||
rect.left > 0 -> {
|
||||
deltaX = -rect.left
|
||||
}
|
||||
rect.right < viewWidth -> {
|
||||
deltaX = viewWidth - rect.right
|
||||
}
|
||||
}
|
||||
zoomMatrix.postTranslate(deltaX, deltaY)
|
||||
}
|
||||
|
||||
private inline val dismissThreshold: Float
|
||||
get() = viewHeight / 3F
|
||||
|
||||
private inline val currentScale: Float
|
||||
get() {
|
||||
zoomMatrix.getValues(matrixValues)
|
||||
return matrixValues[Matrix.MSCALE_X]
|
||||
}
|
||||
|
||||
private inline val currentTransX: Float
|
||||
get() {
|
||||
zoomMatrix.getValues(matrixValues)
|
||||
return matrixValues[Matrix.MTRANS_X]
|
||||
}
|
||||
|
||||
private inline val currentTransY: Float
|
||||
get() {
|
||||
zoomMatrix.getValues(matrixValues)
|
||||
return matrixValues[Matrix.MTRANS_Y]
|
||||
}
|
||||
|
||||
private inline val dismissProgress: Float
|
||||
get() = currentTransY.absoluteValue / dismissThreshold
|
||||
|
||||
private val displayRect: RectF? = RectF()
|
||||
get() {
|
||||
drawable?.let { d ->
|
||||
field?.set(
|
||||
0f, 0f, d.intrinsicWidth.toFloat(), d.intrinsicHeight.toFloat()
|
||||
)
|
||||
drawMatrix.mapRect(field)
|
||||
return field
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private val drawMatrix: Matrix = Matrix()
|
||||
get() {
|
||||
field.set(baseMatrix)
|
||||
field.postConcat(zoomMatrix)
|
||||
return field
|
||||
}
|
||||
|
||||
var currentZoom: Float
|
||||
get() = currentScale
|
||||
set(value) {
|
||||
oldScale = currentScale
|
||||
setScaleAbsolute(value, viewWidth / 2F, viewHeight / 2F)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_SCALE = 3F
|
||||
const val MIN_SCALE = 1F
|
||||
const val MID_SCALE = 1.75F
|
||||
private const val VALUE_ANIMATOR_DURATION = 300L
|
||||
}
|
||||
|
||||
override fun setOnClickListener(l: OnClickListener?) {
|
||||
this.onClickListener = l
|
||||
}
|
||||
|
||||
override fun setOnLongClickListener(l: OnLongClickListener?) {
|
||||
this.onLongClickListener = l
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,19 +6,30 @@ import android.widget.ImageView;
|
|||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
import com.vectras.vm.databinding.IvPrvBinding;
|
||||
import com.vectras.vm.utils.UIUtils;
|
||||
|
||||
public class ImagePrvActivity extends AppCompatActivity {
|
||||
public static String linkIv;
|
||||
public ImageView ivPrv;
|
||||
IvPrvBinding binding;
|
||||
boolean isInvertedBackground;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
UIUtils.edgeToEdge(this);
|
||||
setContentView(R.layout.iv_prv);
|
||||
binding = IvPrvBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
UIUtils.setOnApplyWindowInsetsListener(findViewById(R.id.main));
|
||||
ivPrv = findViewById(R.id.ivPrv);
|
||||
Glide.with(this).load(linkIv).into(ivPrv);
|
||||
if (getIntent().hasExtra("uri")) {
|
||||
Glide.with(this).load(getIntent().getStringExtra("uri")).placeholder(R.drawable.progress_activity_24px).error(R.drawable.broken_image_24px).into(binding.ivPrv);
|
||||
}
|
||||
|
||||
binding.btnChangeBackground.setOnClickListener(v -> {
|
||||
int newBackgroundColor = MaterialColors.getColor(binding.main, isInvertedBackground ? com.google.android.material.R.attr.colorSurface : com.google.android.material.R.attr.colorOnSurface);
|
||||
binding.main.setBackgroundColor(newBackgroundColor);
|
||||
UIUtils.setLightStatusBar(UIUtils.isColorLight(newBackgroundColor), ImagePrvActivity.this);
|
||||
isInvertedBackground = !isInvertedBackground;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,6 +233,15 @@ public class RomInfo extends AppCompatActivity {
|
|||
binding.tvFilename.setText(getIntent().getStringExtra("filename"));
|
||||
}
|
||||
|
||||
binding.ivIcon.setOnClickListener(v -> {
|
||||
if (getIntent().hasExtra("icon")) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("uri", getIntent().getStringExtra("icon"));
|
||||
intent.setClass(getApplicationContext(), ImagePrvActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
binding.lnViews.setOnClickListener((v -> DialogUtils.oneDialog(
|
||||
RomInfo.this,
|
||||
getString(R.string.views),
|
||||
|
|
@ -540,7 +549,7 @@ public class RomInfo extends AppCompatActivity {
|
|||
case "X86_64" -> getString(R.string.x86_64);
|
||||
case "i386" -> getString(R.string.i386_qemu);
|
||||
case "ARM64" -> getString(R.string.arm64_qemu);
|
||||
case "PowerPC" -> getString(R.string.powerpc_qemu);
|
||||
case "PPC" -> getString(R.string.powerpc_qemu);
|
||||
default -> getString(R.string.unknow);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,22 +168,22 @@ public class StoreItemActivity extends AppCompatActivity {
|
|||
itemPrvMain.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ImagePrvActivity.linkIv = prvMain;
|
||||
startActivity(new Intent(activity, ImagePrvActivity.class));
|
||||
// ImagePrvActivity.linkIv = prvMain;
|
||||
// startActivity(new Intent(activity, ImagePrvActivity.class));
|
||||
}
|
||||
});
|
||||
itemPrv1.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ImagePrvActivity.linkIv = prv1;
|
||||
startActivity(new Intent(activity, ImagePrvActivity.class));
|
||||
// ImagePrvActivity.linkIv = prv1;
|
||||
// startActivity(new Intent(activity, ImagePrvActivity.class));
|
||||
}
|
||||
});
|
||||
itemPrv2.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ImagePrvActivity.linkIv = prv2;
|
||||
startActivity(new Intent(activity, ImagePrvActivity.class));
|
||||
// ImagePrvActivity.linkIv = prv2;
|
||||
// startActivity(new Intent(activity, ImagePrvActivity.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -561,8 +561,8 @@ public class VMCreatorActivity extends AppCompatActivity {
|
|||
created = true;
|
||||
|
||||
if (getIntent().hasExtra("addromnow")) {
|
||||
RomStoreActivity.isFinishNow = true;
|
||||
RomInfo.isFinishNow = true;
|
||||
HomeActivity.isOpenHome = true;
|
||||
}
|
||||
|
||||
modify = false;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
|
@ -37,6 +39,7 @@ import com.vectras.vm.settings.VNCSettingsActivity;
|
|||
import com.vectras.vm.utils.DialogUtils;
|
||||
import com.vectras.vm.utils.FileUtils;
|
||||
import com.vectras.vm.utils.JSONUtils;
|
||||
import com.vectras.vm.utils.TextUtils;
|
||||
import com.vectras.vm.utils.UIUtils;
|
||||
import com.vectras.vterm.Terminal;
|
||||
|
||||
|
|
@ -131,17 +134,39 @@ public class VMManager {
|
|||
|
||||
DialogUtils.threeDialog(_activity, _activity.getString(R.string.remove)+ " " + _vmName, _activity.getString(R.string.remove_vm_content), _activity.getString(R.string.remove_and_do_not_keep_files), _activity.getString(R.string.remove_but_keep_files), _activity.getString(R.string.cancel),true, R.drawable.delete_24px, true,
|
||||
() -> {
|
||||
isKeptSomeFiles = false;
|
||||
deleteVM();
|
||||
removeInRomsDataJson(_activity, _vmName, _position);
|
||||
},
|
||||
() -> {
|
||||
hideVMIDWithPosition();
|
||||
removeInRomsDataJson(_activity, _vmName, _position);
|
||||
},
|
||||
() -> {
|
||||
View progressView = LayoutInflater.from(_activity).inflate(R.layout.dialog_progress_style, null);
|
||||
TextView progress_text = progressView.findViewById(R.id.progress_text);
|
||||
progress_text.setText(_activity.getString(R.string.just_a_moment));
|
||||
AlertDialog progressDialog = new MaterialAlertDialogBuilder(_activity, R.style.CenteredDialogTheme)
|
||||
.setView(progressView)
|
||||
.setCancelable(false)
|
||||
.create();
|
||||
progressDialog.show();
|
||||
|
||||
new Thread(() -> {
|
||||
isKeptSomeFiles = false;
|
||||
deleteVM();
|
||||
removeInRomsDataJson(_activity, _vmName, _position);
|
||||
_activity.runOnUiThread(() -> new Handler(Looper.getMainLooper()).postDelayed(progressDialog::dismiss, 500));
|
||||
}).start();
|
||||
},
|
||||
() -> {
|
||||
View progressView = LayoutInflater.from(_activity).inflate(R.layout.dialog_progress_style, null);
|
||||
TextView progress_text = progressView.findViewById(R.id.progress_text);
|
||||
progress_text.setText(_activity.getString(R.string.just_a_moment));
|
||||
AlertDialog progressDialog = new MaterialAlertDialogBuilder(_activity, R.style.CenteredDialogTheme)
|
||||
.setView(progressView)
|
||||
.setCancelable(false)
|
||||
.create();
|
||||
progressDialog.show();
|
||||
|
||||
new Thread(() -> {
|
||||
hideVMIDWithPosition();
|
||||
removeInRomsDataJson(_activity, _vmName, _position);
|
||||
_activity.runOnUiThread(() -> new Handler(Looper.getMainLooper()).postDelayed(progressDialog::dismiss, 500));
|
||||
}).start();
|
||||
},
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
|
|
@ -181,35 +206,14 @@ public class VMManager {
|
|||
|
||||
@NonNull
|
||||
public static String startRamdomVMID() {
|
||||
String addAdb;
|
||||
Random random = new Random();
|
||||
int randomAbc = random.nextInt(12);
|
||||
if (randomAbc == 0) {
|
||||
addAdb = "a";
|
||||
} else if (randomAbc == 1) {
|
||||
addAdb = "b";
|
||||
} else if (randomAbc == 2) {
|
||||
addAdb = "c";
|
||||
} else if (randomAbc == 3) {
|
||||
addAdb = "d";
|
||||
} else if (randomAbc == 4) {
|
||||
addAdb = "e";
|
||||
} else if (randomAbc == 5) {
|
||||
addAdb = "f";
|
||||
} else if (randomAbc == 6) {
|
||||
addAdb = "g";
|
||||
} else if (randomAbc == 7) {
|
||||
addAdb = "h";
|
||||
} else if (randomAbc == 8) {
|
||||
addAdb = "i";
|
||||
} else if (randomAbc == 9) {
|
||||
addAdb = "j";
|
||||
} else if (randomAbc == 10) {
|
||||
addAdb = "k";
|
||||
} else {
|
||||
addAdb = "l";
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
result.append(random.nextInt(2) > 0 ? TextUtils.randomALetter() : String.valueOf(random.nextInt(10)));
|
||||
}
|
||||
return addAdb + (long) (random.nextInt(65535));
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static int startRandomPort() {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
|
|||
private final String TAG = "HomeActivity";
|
||||
public static boolean isActivate = false;
|
||||
public static boolean isNeedRecreate = false;
|
||||
public static boolean isOpenHome = false;
|
||||
public static boolean isOpenRomStore = false;
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
ActivityHomeBinding binding;
|
||||
|
|
@ -336,6 +337,10 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
|
|||
if (isOpenRomStore) {
|
||||
isOpenRomStore = false;
|
||||
bindingContent.bottomNavigation.setSelectedItemId(R.id.item_romstore);
|
||||
} else if (isOpenHome) {
|
||||
isOpenHome = false;
|
||||
if (binding.searchview.isShowing()) binding.searchview.hide();
|
||||
bindingContent.bottomNavigation.setSelectedItemId(R.id.item_home);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
|
@ -20,6 +21,7 @@ import android.widget.BaseAdapter;
|
|||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
|
@ -81,6 +83,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
|
|||
boolean isLibProotError = false;
|
||||
boolean aria2Error = false;
|
||||
boolean isServerError = false;
|
||||
boolean isNotEnoughStorageSpace = false;
|
||||
boolean isCustomSetupMode = false;
|
||||
final ArrayList<HashMap<String, String>> mirrorList = new ArrayList<>();
|
||||
|
||||
|
|
@ -117,6 +120,12 @@ public class SetupWizard2Activity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
loadingIndicatorController(currentStep);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
tarPath = getExternalFilesDir("data") + "/data.tar.gz";
|
||||
|
||||
|
|
@ -237,9 +246,14 @@ public class SetupWizard2Activity extends AppCompatActivity {
|
|||
binding.lnInstallingPackages.setVisibility(View.VISIBLE);
|
||||
} else if (step == STEP_ERROR) {
|
||||
binding.lnInstallingPackagesFailed.setVisibility(View.VISIBLE);
|
||||
binding.tvErrorLogContent.setText(log);
|
||||
binding.tvErrorLogContent.setText(log.isEmpty() ? getString(R.string.there_are_no_logs) : log);
|
||||
|
||||
if (isLibProotError) {
|
||||
if (isNotEnoughStorageSpace) {
|
||||
binding.ivErrorLarge.setImageResource(R.drawable.disc_full_100px);
|
||||
binding.tvErrorTitle.setText(getString(R.string.not_enough_storage_space));
|
||||
binding.tvErrorSubtitle.setText(getString(R.string.not_enough_storage_to_set_up_content));
|
||||
binding.btnTryAgain.setText(getString(R.string.join_our_community));
|
||||
} else if (isLibProotError) {
|
||||
binding.ivErrorLarge.setImageResource(R.drawable.error_96px);
|
||||
binding.tvErrorTitle.setText(getString(R.string.vectras_vm_cannot_run_on_this_device));
|
||||
binding.tvErrorSubtitle.setText(getString(R.string.a_serious_problem_has_occurred));
|
||||
|
|
@ -257,9 +271,54 @@ public class SetupWizard2Activity extends AppCompatActivity {
|
|||
bindingFinalSteps.main.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
loadingIndicatorController(step);
|
||||
|
||||
currentStep = step;
|
||||
}
|
||||
|
||||
private void loadingIndicatorController(int step) {
|
||||
float dp = 200f;
|
||||
float px = dp * getResources().getDisplayMetrics().density;
|
||||
|
||||
if (step == STEP_EXTRACTING_SYSTEM_FILES) {
|
||||
binding.lnExtractingSystemFilesCpiContainer.post(() -> {
|
||||
int heightPx = binding.lnExtractingSystemFilesCpiContainer.getHeight();
|
||||
|
||||
if (heightPx < px) {
|
||||
binding.cpiExtractingSystemFiles.setVisibility(View.GONE);
|
||||
binding.lpiExtractingSystemFiles.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.cpiExtractingSystemFiles.setVisibility(View.VISIBLE);
|
||||
binding.lpiExtractingSystemFiles.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
} else if (step == STEP_GETTING_DATA) {
|
||||
binding.lnGettingDataCpiContainer.post(() -> {
|
||||
int heightPx = binding.lnGettingDataCpiContainer.getHeight();
|
||||
|
||||
if (heightPx < px) {
|
||||
binding.cpiGettingData.setVisibility(View.GONE);
|
||||
binding.lpiGettingData.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.cpiGettingData.setVisibility(View.VISIBLE);
|
||||
binding.lpiGettingData.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
} else if (step == STEP_INSTALLING_PACKAGES) {
|
||||
binding.lnInstallingPackagesCpiContainer.post(() -> {
|
||||
int heightPx = binding.lnInstallingPackagesCpiContainer.getHeight();
|
||||
|
||||
if (heightPx < px) {
|
||||
binding.cpiInstallingPackages.setVisibility(View.GONE);
|
||||
binding.lpiInstallingPackages.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.cpiInstallingPackages.setVisibility(View.VISIBLE);
|
||||
binding.lpiInstallingPackages.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void uiControllerFinalSteps(int step) {
|
||||
TransitionManager.beginDelayedTransition(bindingFinalSteps.mainContent);
|
||||
|
||||
|
|
@ -287,7 +346,14 @@ public class SetupWizard2Activity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void extractSystemFiles() {
|
||||
uiController(STEP_EXTRACTING_SYSTEM_FILES);
|
||||
isNotEnoughStorageSpace = DeviceUtils.isStorageLow(this, false);
|
||||
|
||||
if (isNotEnoughStorageSpace) {
|
||||
uiController(STEP_ERROR);
|
||||
return;
|
||||
} else {
|
||||
uiController(STEP_EXTRACTING_SYSTEM_FILES);
|
||||
}
|
||||
|
||||
new Thread(() -> {
|
||||
boolean result = SetupFeatureCore.startExtractSystemFiles(this);
|
||||
|
|
@ -369,7 +435,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
|
|||
" mkdir -p $TMPDIR/pulse;" +
|
||||
" echo export PULSE_SERVER=127.0.0.1 >> /etc/profile;" +
|
||||
" mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;" +
|
||||
" echo \"installation successful! xssFjnj58Id\"";
|
||||
" echo \"Installation successful! xssFjnj58Id\"";
|
||||
|
||||
executeShellCommand(cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ package com.vectras.vm.utils;
|
|||
import android.app.ActivityManager;
|
||||
import android.app.usage.StorageStatsManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.StatFs;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
|
@ -63,4 +63,16 @@ public class DeviceUtils {
|
|||
public static boolean is64bit() {
|
||||
return Build.SUPPORTED_ABIS[0].contains("arm64");
|
||||
}
|
||||
|
||||
public static boolean isLargeScreen(Context context) {
|
||||
Configuration config = context.getResources().getConfiguration();
|
||||
return config.smallestScreenWidthDp >= 600;
|
||||
}
|
||||
|
||||
public static boolean isHighDpi(Context context) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
int currentDpi = metrics.densityDpi;
|
||||
Log.i(TAG, "isHighDpi: " + currentDpi);
|
||||
return currentDpi >= 600;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
65
app/src/main/java/com/vectras/vm/utils/TextUtils.java
Normal file
65
app/src/main/java/com/vectras/vm/utils/TextUtils.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package com.vectras.vm.utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class TextUtils {
|
||||
public static String randomALetter() {
|
||||
String addAdb;
|
||||
Random random = new Random();
|
||||
int randomAbc = random.nextInt(26);
|
||||
if (randomAbc == 0) {
|
||||
addAdb = "a";
|
||||
} else if (randomAbc == 1) {
|
||||
addAdb = "b";
|
||||
} else if (randomAbc == 2) {
|
||||
addAdb = "c";
|
||||
} else if (randomAbc == 3) {
|
||||
addAdb = "d";
|
||||
} else if (randomAbc == 4) {
|
||||
addAdb = "e";
|
||||
} else if (randomAbc == 5) {
|
||||
addAdb = "f";
|
||||
} else if (randomAbc == 6) {
|
||||
addAdb = "g";
|
||||
} else if (randomAbc == 7) {
|
||||
addAdb = "h";
|
||||
} else if (randomAbc == 8) {
|
||||
addAdb = "i";
|
||||
} else if (randomAbc == 9) {
|
||||
addAdb = "j";
|
||||
} else if (randomAbc == 10) {
|
||||
addAdb = "k";
|
||||
} else if (randomAbc == 11) {
|
||||
addAdb = "l";
|
||||
} else if (randomAbc == 12) {
|
||||
addAdb = "m";
|
||||
} else if (randomAbc == 13) {
|
||||
addAdb = "n";
|
||||
} else if (randomAbc == 14) {
|
||||
addAdb = "o";
|
||||
} else if (randomAbc == 15) {
|
||||
addAdb = "p";
|
||||
} else if (randomAbc == 16) {
|
||||
addAdb = "q";
|
||||
} else if (randomAbc == 17) {
|
||||
addAdb = "r";
|
||||
} else if (randomAbc == 18) {
|
||||
addAdb = "s";
|
||||
} else if (randomAbc == 19) {
|
||||
addAdb = "t";
|
||||
} else if (randomAbc == 20) {
|
||||
addAdb = "u";
|
||||
} else if (randomAbc == 21) {
|
||||
addAdb = "v";
|
||||
} else if (randomAbc == 22) {
|
||||
addAdb = "w";
|
||||
} else if (randomAbc == 23) {
|
||||
addAdb = "x";
|
||||
} else if (randomAbc == 24) {
|
||||
addAdb = "y";
|
||||
} else {
|
||||
addAdb = "z";
|
||||
}
|
||||
return addAdb;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.appcompat.app.AlertDialog;
|
|||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import android.content.ClipData;
|
||||
|
|
@ -32,6 +33,8 @@ import android.util.Log;
|
|||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ScrollView;
|
||||
|
|
@ -524,4 +527,13 @@ public class UIUtils {
|
|||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setLightStatusBar(boolean isEnable, Activity _activity) {
|
||||
Window window = _activity.getWindow();
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
|
||||
WindowCompat.getInsetsController(window, window.getDecorView())
|
||||
.setAppearanceLightStatusBars(isEnable);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
app/src/main/res/drawable/broken_image_24px.xml
Normal file
10
app/src/main/res/drawable/broken_image_24px.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM240,503L400,343L560,503L720,343L760,383L760,200Q760,200 760,200Q760,200 760,200L200,200Q200,200 200,200Q200,200 200,200L200,463L240,503ZM200,760L760,760Q760,760 760,760Q760,760 760,760L760,496L720,456L560,616L400,456L240,616L200,576L200,760Q200,760 200,760Q200,760 200,760ZM200,760L200,760Q200,760 200,760Q200,760 200,760L200,496L200,576L200,463L200,383L200,200Q200,200 200,200Q200,200 200,200L200,200Q200,200 200,200Q200,200 200,200L200,463L200,463L200,576L200,576L200,760Q200,760 200,760Q200,760 200,760Z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/disc_full_100px.xml
Normal file
10
app/src/main/res/drawable/disc_full_100px.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="100dp"
|
||||
android:height="100dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,660Q555,660 607.5,607.5Q660,555 660,480Q660,405 607.5,352.5Q555,300 480,300Q405,300 352.5,352.5Q300,405 300,480Q300,555 352.5,607.5Q405,660 480,660ZM480,520Q463,520 451.5,508.5Q440,497 440,480Q440,463 451.5,451.5Q463,440 480,440Q497,440 508.5,451.5Q520,463 520,480Q520,497 508.5,508.5Q497,520 480,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q600,80 699,145.5Q798,211 846,320L756,320Q714,245 640,202.5Q566,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800Q549,800 612,771.5Q675,743 720,690L720,800Q667,838 606,859Q545,880 480,880ZM800,720L800,400L880,400L880,720L800,720ZM840,880Q823,880 811.5,868.5Q800,857 800,840Q800,823 811.5,811.5Q823,800 840,800Q857,800 868.5,811.5Q880,823 880,840Q880,857 868.5,868.5Q857,880 840,880ZM480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/progress_activity_24px.xml
Normal file
10
app/src/main/res/drawable/progress_activity_24px.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,880Q398,880 325,848.5Q252,817 197.5,762.5Q143,708 111.5,635Q80,562 80,480Q80,397 111.5,324.5Q143,252 197.5,197.5Q252,143 325,111.5Q398,80 480,80Q497,80 508.5,91.5Q520,103 520,120Q520,137 508.5,148.5Q497,160 480,160Q347,160 253.5,253.5Q160,347 160,480Q160,613 253.5,706.5Q347,800 480,800Q613,800 706.5,706.5Q800,613 800,480Q800,463 811.5,451.5Q823,440 840,440Q857,440 868.5,451.5Q880,463 880,480Q880,562 848.5,635Q817,708 762.5,762.5Q708,817 635.5,848.5Q563,880 480,880Z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/shadow_24px.xml
Normal file
10
app/src/main/res/drawable/shadow_24px.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,880Q127,880 103.5,856.5Q80,833 80,800L80,320Q80,287 103.5,263.5Q127,240 160,240L240,240L240,160Q240,127 263.5,103.5Q287,80 320,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L720,720L720,800Q720,833 696.5,856.5Q673,880 640,880L160,880ZM320,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L320,160Q320,160 320,160Q320,160 320,160L320,640Q320,640 320,640Q320,640 320,640Z"/>
|
||||
</vector>
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
style="?attr/materialCardViewFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="?attr/colorSurfaceContainer">
|
||||
app:cardBackgroundColor="?attr/colorCard">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="25dp"
|
||||
android:background="?attr/colorSurfaceContainerHigh"/>
|
||||
android:background="?attr/colorSurfaceContainerHighest"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
@ -159,7 +159,7 @@
|
|||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="25dp"
|
||||
android:background="?attr/colorSurfaceContainerHigh"/>
|
||||
android:background="?attr/colorSurfaceContainerHighest"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_creator"
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="25dp"
|
||||
android:background="?attr/colorSurfaceContainerHigh"/>
|
||||
android:background="?attr/colorSurfaceContainerHighest"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_arch"
|
||||
|
|
@ -215,7 +215,7 @@
|
|||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="25dp"
|
||||
android:background="?attr/colorSurfaceContainerHigh"/>
|
||||
android:background="?attr/colorSurfaceContainerHighest"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_size"
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="25dp"
|
||||
android:background="?attr/colorSurfaceContainerHigh"/>
|
||||
android:background="?attr/colorSurfaceContainerHighest"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_filename"
|
||||
|
|
|
|||
|
|
@ -105,12 +105,22 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/just_a_sec" />
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/lpi_extracting_system_files"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_extracting_system_files_cpi_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/cpi_extracting_system_files"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
|
|
@ -141,13 +151,22 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/just_a_sec" />
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/lpi_getting_data"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_getting_data_cpi_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/cpi_getting_data"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
|
|
@ -372,13 +391,23 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/please_do_not_disconnect_the_network_this_may_take_a_few_minutes" />
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/lpi_installing_packages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_installing_packages_cpi_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/cpi_installing_packages"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
|
|
|
|||
|
|
@ -3,13 +3,23 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ImagePrvActivity"
|
||||
android:id="@+id/main">
|
||||
<ImageView
|
||||
<com.k2.zoomimageview.ZoomImageView
|
||||
android:id="@+id/ivPrv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_change_background"
|
||||
style="@style/Widget.Material3Expressive.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:padding="8dp"
|
||||
android:layout_margin="16dp"
|
||||
app:icon="@drawable/shadow_24px" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
<string name="app_name">Vectras VM</string>
|
||||
|
||||
<!--======================VECTRAS STRINGS====================-->
|
||||
<string name="app_version" translatable="false">3.3.9</string>
|
||||
<string name="app_version" translatable="false">3.4.0</string>
|
||||
<string name="qemu_version" translatable="false">Stable</string>
|
||||
<!-- logger -->
|
||||
<string name="startvm">VM STARTED!</string>
|
||||
|
|
@ -454,6 +454,8 @@
|
|||
<string name="the_setup_could_not_be_completed_and_below_is_the_log">The setup could not be completed and below is the log.</string>
|
||||
<string name="this_option_is_temporarily_unavailable_because_the_server_cannot_be_connected">This option is temporarily unavailable because the server cannot be connected.</string>
|
||||
<string name="vectras_vm_cannot_run_on_this_device">Vectras VM cannot run on this device.</string>
|
||||
<string name="not_enough_storage_space">Not enough storage space.</string>
|
||||
<string name="there_are_no_logs">There are no logs.</string>
|
||||
|
||||
|
||||
<!--======================TERMUX STRINGS====================-->
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '2.2.0'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.13.1' // Android Gradle plugin
|
||||
classpath 'com.android.tools.build:gradle:8.13.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
// Android Gradle plugin
|
||||
// Add other classpaths like Google Services and Firebase Crashlytics if needed here.
|
||||
// classpath 'com.google.gms:google-services:4.4.3' // assuming you need it for your project
|
||||
// classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.6'
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versionCode":"34",
|
||||
"versionName":"3.3.0",
|
||||
"size": "60 MB",
|
||||
"versionCode":"44",
|
||||
"versionName":"3.4.0",
|
||||
"size": "55 MB",
|
||||
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
|
||||
"Message": "<h2>3.3.0</h2>New Qemu 9.2.2 with 3dfx! And bugs fixed.",
|
||||
"Message": "<h2>3.4.0</h2>\n- Fixed the issue of exporting rom with virtual machine ID.\n- New dialog for copying files in creating new virtual machine.\n- New dialog showing information after successful rom import.\n- Fixed no sound playing with Termux.\n- Fixed invalid file path error when using Manual setup.\n- Fixed dialog showing content without line breaks.\n- Fixed rom export error.\n- Added Processes to System monitor.\n- Improved interface.\n- Thinner fonts.\n- Fixed an issue with interaction in Rom store.\n- Fixed the External VNC Server switch being incorrect in certain cases.\n- Removed unnecessary resources.\n- Updated Chinese (Simplified) language (contributed by @WeiguangTWK).\n- Fixed issue with installing system files after not completing the first time.\n- New setup wizard.\n- Added auto return to Home after importing rom and creating virtual machine in Rom store.\n- Improved image viewer.\n- Fixed Unknow display error in architecture in rom info if it is PowerPC architecture.\n- New setup wizard interface that automatically changes according to screen size.\n- New ID generator for virtual machine.\n- Added dialog when deleting virtual machine.",
|
||||
"cancellable": true,
|
||||
"versionCodeBeta":"43",
|
||||
"versionNameBeta":"3.3.9",
|
||||
"versionCodeBeta":"44",
|
||||
"versionNameBeta":"3.4.0",
|
||||
"versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9",
|
||||
"sizeBeta": "55 MB",
|
||||
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
|
||||
"MessageBeta": "<h2>3.3.9</h2>Bugs fixed.",
|
||||
"MessageBeta": "<h2>3.4.0</h2>Bugs fixed.",
|
||||
"cancellableBeta": true
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue