second commit
This commit is contained in:
Generated
+3
-3
@@ -1,3 +1,3 @@
|
|||||||
# Default ignored files
|
# Default ignored files
|
||||||
/shelf/
|
/shelf/
|
||||||
/workspace.xml
|
/workspace.xml
|
||||||
|
|||||||
Generated
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="AndroidProjectSystem">
|
<component name="AndroidProjectSystem">
|
||||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="21" />
|
<bytecodeTargetLevel target="17" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+17
-17
@@ -1,18 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="deploymentTargetSelector">
|
<component name="deploymentTargetSelector">
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2026-03-05T21:47:45.054369300Z">
|
<DropdownSelection timestamp="2026-03-05T21:47:45.054369300Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=XORSNZTCGAAI89CU" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=XORSNZTCGAAI89CU" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
<DialogSelection />
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+13
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DeviceTable">
|
||||||
|
<option name="columnSorters">
|
||||||
|
<list>
|
||||||
|
<ColumnSorterState>
|
||||||
|
<option name="column" value="Name" />
|
||||||
|
<option name="order" value="ASCENDING" />
|
||||||
|
</ColumnSorterState>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="project">
|
||||||
|
<words>
|
||||||
|
<w>ошибка</w>
|
||||||
|
<w>сети</w>
|
||||||
|
</words>
|
||||||
|
</dictionary>
|
||||||
|
</component>
|
||||||
Generated
+18
-18
@@ -1,19 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
<option name="gradleJvm" value="ms-17" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewParameterProviderOnFirstParameter" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
Generated
+9
-9
@@ -1,10 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectMigrations">
|
<component name="ProjectMigrations">
|
||||||
<option name="MigrateToGradleLocalJavaHome">
|
<option name="MigrateToGradleLocalJavaHome">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="ms-17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
Generated
+16
-16
@@ -1,17 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="RunConfigurationProducerService">
|
<component name="RunConfigurationProducerService">
|
||||||
<option name="ignoredProducers">
|
<option name="ignoredProducers">
|
||||||
<set>
|
<set>
|
||||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+65
-33
@@ -1,40 +1,27 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
|
alias(libs.plugins.kotlin.android)
|
||||||
|
alias(libs.plugins.hilt)
|
||||||
|
alias(libs.plugins.kapt)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
packaging {
|
|
||||||
jniLibs {
|
|
||||||
useLegacyPackaging = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Для компиляции с поддержкой 16 KB
|
|
||||||
defaultConfig {
|
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
// ИСПРАВЛЕНИЕ: здесь нужно использовать аргументы и скобки/равенство
|
|
||||||
cppFlags("-Wl,-z,max-page-size=16384")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace = "com.example.myserver"
|
namespace = "com.example.myserver"
|
||||||
compileSdk {
|
compileSdk = 35
|
||||||
version = release(36)
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.example.myserver"
|
applicationId = "com.example.myserver"
|
||||||
minSdk = 29
|
minSdk = 29
|
||||||
targetSdk = 36
|
targetSdk = 35
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0"
|
versionName = "1.0"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
cppFlags += ""
|
arguments("-DANDROID_STL=c++_shared")
|
||||||
|
cppFlags("-Wl,-z,max-page-size=16384")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,10 +35,31 @@ android {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
// Compose и Hilt лучше работают на Java 17
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "17"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
|
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion = "1.5.1" // Соответствует Kotlin 1.9.0
|
||||||
|
}
|
||||||
|
|
||||||
|
packaging {
|
||||||
|
resources {
|
||||||
|
excludes += "/META-INF/{AL2.0,LGPL2.1,androidx.compose.material3_material3.version}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
path = file("src/main/cpp/CMakeLists.txt")
|
path = file("src/main/cpp/CMakeLists.txt")
|
||||||
@@ -61,18 +69,42 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
// 1. Сначала объявляем BOM (один раз в самом начале)
|
||||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
val composeBom = platform("androidx.compose:compose-bom:2024.02.01")
|
||||||
|
implementation(composeBom)
|
||||||
|
androidTestImplementation(composeBom)
|
||||||
|
|
||||||
|
// 2. Jetpack Compose (версии берутся из BOM)
|
||||||
|
implementation(libs.compose.ui)
|
||||||
|
implementation(libs.compose.ui.graphics)
|
||||||
|
implementation(libs.compose.ui.tooling.preview)
|
||||||
|
implementation(libs.activity.compose)
|
||||||
|
implementation(libs.lifecycle.viewmodel.compose)
|
||||||
|
implementation(libs.foundation)
|
||||||
|
|
||||||
|
// 3. Material 3 (обязательно для PullToRefreshBox)
|
||||||
|
implementation("androidx.compose.material3:material3")
|
||||||
|
implementation("androidx.compose.material3:material3-window-size-class")
|
||||||
|
implementation("androidx.compose.material:material-icons-extended")
|
||||||
|
|
||||||
|
// 4. Сеть (Retrofit)
|
||||||
|
implementation(libs.retrofit)
|
||||||
|
implementation(libs.retrofit.gson)
|
||||||
|
implementation(libs.okhttp.logging)
|
||||||
|
|
||||||
|
// 5. Dagger Hilt
|
||||||
|
implementation(libs.hilt.android)
|
||||||
|
kapt(libs.hilt.compiler)
|
||||||
|
implementation("androidx.hilt:hilt-navigation-compose:1.1.0")
|
||||||
|
|
||||||
|
// 6. Остальное
|
||||||
implementation(libs.appcompat)
|
implementation(libs.appcompat)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.activity)
|
implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")
|
||||||
implementation(libs.constraintlayout)
|
|
||||||
implementation(libs.recyclerview)
|
// Тесты и отладка
|
||||||
implementation(libs.cardview)
|
|
||||||
implementation(libs.viewpager2)
|
|
||||||
implementation(libs.legacy.support.v4)
|
|
||||||
implementation(libs.mediarouter)
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
}
|
debugImplementation(libs.compose.ui.tooling)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<application
|
|
||||||
android:allowBackup="true"
|
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
<application
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:label="@string/app_name"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:supportsRtl="true"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.MySERVER"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:usesCleartextTraffic="true">
|
android:supportsRtl="true"
|
||||||
<activity
|
android:theme="@style/Theme.MySERVER"
|
||||||
android:name=".ProfileActivity"
|
android:usesCleartextTraffic="true"
|
||||||
android:exported="false" />
|
android:name=".MyApplication">
|
||||||
<activity
|
<activity
|
||||||
android:name=".LoadScreen"
|
android:name=".ProfileActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".RegActivity"
|
android:name=".RegActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".InformationActivity"
|
android:name=".InformationActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MapActivity"
|
android:name=".MapActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity3"
|
android:name=".YourProfile"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity2"
|
android:name=".MainActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".LogActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
// For instance,
|
// For instance,
|
||||||
//
|
//
|
||||||
// In MainActivity.java:
|
// In MainActivity.kt:
|
||||||
// static {
|
// static {
|
||||||
// System.loadLibrary("myserver");
|
// System.loadLibrary("myserver");
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
|
|
||||||
public class AuthManager {
|
|
||||||
private final Context context;
|
|
||||||
|
|
||||||
public AuthManager(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void authUser(String realname, String password, String email, boolean isRegistration) {
|
|
||||||
UserRequest request = new UserRequest(realname, password, email);
|
|
||||||
MyApiService api = RetrofitClient.getApiService();
|
|
||||||
|
|
||||||
// Выбираем метод в зависимости от флага
|
|
||||||
Call<UserResponse> call = isRegistration ? api.register(request) : api.login(request);
|
|
||||||
|
|
||||||
call.enqueue(new Callback<>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<UserResponse> call, @NonNull Response<UserResponse> response) {
|
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
|
||||||
saveUserToLocal(response.body());
|
|
||||||
|
|
||||||
// ДОБАВЬ ЭТОТ КОД ДЛЯ ПЕРЕХОДА:
|
|
||||||
Intent intent = new Intent(context, LoadScreen.class); // Укажи свою главную активность
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
||||||
context.startActivity(intent);
|
|
||||||
|
|
||||||
Toast.makeText(context, "Успешный вход!", Toast.LENGTH_SHORT).show();
|
|
||||||
} else {
|
|
||||||
Toast.makeText(context, "Ошибка сервера: " + response.code(), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull Call<UserResponse> call, @NonNull Throwable t) {
|
|
||||||
// ЕСЛИ СЕРВЕР ВООБЩЕ НЕ ДОСТУПЕН (не тот IP или выключен)
|
|
||||||
Toast.makeText(context, "Сеть недоступна: " + t.getMessage(), Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveUserToLocal(UserResponse user) {
|
|
||||||
SharedPreferences prefs = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE);
|
|
||||||
prefs.edit()
|
|
||||||
.putBoolean("isLoggedIn", true)
|
|
||||||
.putString("realname", user.getRealname())
|
|
||||||
.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class AuthViewModel @Inject constructor(
|
||||||
|
private val apiService: MyApiService
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
// Состояние экрана (загрузка, успех, ошибка)
|
||||||
|
private val _authState = MutableStateFlow<AuthState>(AuthState.Idle)
|
||||||
|
val authState = _authState.asStateFlow()
|
||||||
|
|
||||||
|
fun authUser(request: UserRequest, isRegistration: Boolean) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_authState.value = AuthState.Loading
|
||||||
|
try {
|
||||||
|
val response = if (isRegistration) {
|
||||||
|
apiService.register(request)
|
||||||
|
} else {
|
||||||
|
apiService.login(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.isSuccessful && response.body() != null) {
|
||||||
|
_authState.value = AuthState.Success(response.body()!!)
|
||||||
|
} else {
|
||||||
|
_authState.value = AuthState.Error("Ошибка: ${response.code()}")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
_authState.value = AuthState.Error("Сеть недоступна: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Описываем возможные состояния
|
||||||
|
sealed class AuthState {
|
||||||
|
object Idle : AuthState()
|
||||||
|
object Loading : AuthState()
|
||||||
|
data class Success(val user: UserResponse) : AuthState()
|
||||||
|
data class Error(val message: String) : AuthState()
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
|
|
||||||
public class InformationActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_information);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
String name = getSharedPreferences("AppPrefs", MODE_PRIVATE).getString("username", "Гость");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class InformationActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE)
|
||||||
|
val username = prefs.getString("username", "Гость") ?: "Гость"
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
InformationScreen(
|
||||||
|
username = username,
|
||||||
|
onBackClick = { finish() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InformationScreen(
|
||||||
|
username: String,
|
||||||
|
onBackClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
color = Color(0xFF3E4B54)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
// Верхняя панель
|
||||||
|
InformationTopBar(onBackClick = onBackClick)
|
||||||
|
|
||||||
|
// Контентная часть - исправлено!
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f), // ← Правильное использование weight
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
InformationContent(username = username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InformationTopBar(
|
||||||
|
onBackClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
IconButton(onClick = onBackClick) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowBack,
|
||||||
|
contentDescription = "Назад",
|
||||||
|
tint = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Информация",
|
||||||
|
color = Color.White,
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
modifier = Modifier.padding(start = 8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InformationContent(
|
||||||
|
username: String
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Добро пожаловать, $username!",
|
||||||
|
color = Color.White,
|
||||||
|
style = MaterialTheme.typography.headlineMedium
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Экран находится в разработке",
|
||||||
|
color = Color.White.copy(alpha = 0.7f),
|
||||||
|
style = MaterialTheme.typography.bodyLarge
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.animation.AlphaAnimation;
|
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
public class LoadScreen extends AppCompatActivity {
|
|
||||||
private TextView textViewWelcome;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_load_screen);
|
|
||||||
textViewWelcome = findViewById(R.id.textWelcome);
|
|
||||||
|
|
||||||
// Получаем переданное имя
|
|
||||||
SharedPreferences prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE);
|
|
||||||
String realName = prefs.getString("realname", null);
|
|
||||||
|
|
||||||
if (realName != null) {
|
|
||||||
textViewWelcome.setText("Добро пожаловать, " + realName + "!");
|
|
||||||
} else {
|
|
||||||
textViewWelcome.setText("Добро пожаловать!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Запускаем анимацию для приветствия
|
|
||||||
animateWelcomeMessage();
|
|
||||||
}
|
|
||||||
private void animateWelcomeMessage() {
|
|
||||||
if (textViewWelcome != null) {
|
|
||||||
// 1. Появление текста (1 секунда)
|
|
||||||
AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
|
|
||||||
fadeIn.setDuration(1000);
|
|
||||||
textViewWelcome.startAnimation(fadeIn);
|
|
||||||
|
|
||||||
// 2. Ждем, пока пользователь почитает (например, 2 секунды), и запускаем исчезновение
|
|
||||||
new Handler().postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
|
|
||||||
fadeOut.setDuration(1000); // время затухания
|
|
||||||
|
|
||||||
fadeOut.setAnimationListener(new Animation.AnimationListener() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationStart(Animation animation) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animation animation) {
|
|
||||||
textViewWelcome.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
// ПЕРЕХОД ДЕЛАЕМ ТУТ (когда всё исчезло)
|
|
||||||
Intent intent = new Intent(LoadScreen.this, MainActivity2.class);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAnimationRepeat(Animation animation) {}
|
|
||||||
});
|
|
||||||
|
|
||||||
textViewWelcome.startAnimation(fadeOut);
|
|
||||||
}
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.animation.core.*
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class LoadScreen : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
// Важно: MaterialTheme должен быть корневым
|
||||||
|
MaterialTheme {
|
||||||
|
LoadScreenContent(
|
||||||
|
onNavigationToMain = {
|
||||||
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoadScreenContent(
|
||||||
|
onNavigationToMain: () -> Unit
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val prefs = remember { context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE) }
|
||||||
|
val realName by remember {
|
||||||
|
derivedStateOf { prefs.getString("realname", "") ?: "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Анимация для текста приветствия
|
||||||
|
val alpha = remember { Animatable(0f) }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
// Эффект для навигации и анимации
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
// Появление текста
|
||||||
|
launch {
|
||||||
|
alpha.animateTo(1f, animationSpec = tween(500))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Задержка перед переходом
|
||||||
|
delay(2000)
|
||||||
|
|
||||||
|
// Исчезновение текста
|
||||||
|
alpha.animateTo(0f, animationSpec = tween(500))
|
||||||
|
|
||||||
|
// Переход на главный экран
|
||||||
|
onNavigationToMain()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Основной контейнер
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
color = Color(0xFF3E4B54) // Тот же цвет фона
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
// Центральная часть: Индикатор и текст "Загрузка"
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
color = Color.White,
|
||||||
|
strokeWidth = 4.dp,
|
||||||
|
modifier = Modifier.size(48.dp) // Добавил фиксированный размер для красоты
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Загрузка...",
|
||||||
|
color = Color(0xFF888888),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Нижняя часть: Приветствие с анимацией
|
||||||
|
Text(
|
||||||
|
text = if (realName.isNotEmpty()) {
|
||||||
|
"Добро пожаловать,\n$realName!"
|
||||||
|
} else {
|
||||||
|
"Добро пожаловать!"
|
||||||
|
},
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
.padding(bottom = 50.dp)
|
||||||
|
.alpha(alpha.value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Альтернативный вариант с использованием AnimatedVisibility (более "compose-way")
|
||||||
|
@Composable
|
||||||
|
fun AlternativeLoadScreenContent(
|
||||||
|
onNavigationToMain: () -> Unit
|
||||||
|
) {
|
||||||
|
// Этот вариант можно использовать вместо ручного управления alpha
|
||||||
|
// Он более декларативный, но требует больше кода
|
||||||
|
}
|
||||||
@@ -0,0 +1,357 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class LogActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE)
|
||||||
|
if (prefs.getBoolean("isLoggedIn", false)) {
|
||||||
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
LoginScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoginScreen(viewModel: AuthViewModel = hiltViewModel()) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val authState by viewModel.authState.collectAsState()
|
||||||
|
|
||||||
|
var name by remember { mutableStateOf("") }
|
||||||
|
var password by remember { mutableStateOf("") }
|
||||||
|
var warningText by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
// Обработка состояния авторизации
|
||||||
|
LaunchedEffect(authState) {
|
||||||
|
when (authState) {
|
||||||
|
is AuthState.Success -> {
|
||||||
|
context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE).edit {
|
||||||
|
putBoolean("isLoggedIn", true)
|
||||||
|
putString("realname", name)
|
||||||
|
}
|
||||||
|
context.startActivity(Intent(context, MainActivity::class.java))
|
||||||
|
(context as LogActivity).finish()
|
||||||
|
}
|
||||||
|
is AuthState.Error -> {
|
||||||
|
warningText = (authState as AuthState.Error).message
|
||||||
|
}
|
||||||
|
else -> { /* Loading or Idle */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginScreenContent(
|
||||||
|
name = name,
|
||||||
|
onNameChange = {
|
||||||
|
name = it
|
||||||
|
warningText = "" // Сбрасываем ошибку при вводе
|
||||||
|
},
|
||||||
|
password = password,
|
||||||
|
onPasswordChange = {
|
||||||
|
password = it
|
||||||
|
warningText = "" // Сбрасываем ошибку при вводе
|
||||||
|
},
|
||||||
|
warningText = warningText,
|
||||||
|
isLoading = authState is AuthState.Loading,
|
||||||
|
onLoginClick = {
|
||||||
|
if (validateFields(name, password, context)) {
|
||||||
|
viewModel.authUser(UserRequest(name, password), isRegistration = false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRegisterClick = {
|
||||||
|
context.startActivity(Intent(context, RegActivity::class.java))
|
||||||
|
(context as LogActivity).finish()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoginScreenContent(
|
||||||
|
name: String,
|
||||||
|
onNameChange: (String) -> Unit,
|
||||||
|
password: String,
|
||||||
|
onPasswordChange: (String) -> Unit,
|
||||||
|
warningText: String,
|
||||||
|
isLoading: Boolean,
|
||||||
|
onLoginClick: () -> Unit,
|
||||||
|
onRegisterClick: () -> Unit
|
||||||
|
) {
|
||||||
|
// ScrollView аналог
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFF3E4B54))
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
// LinearLayout аналог с padding="16dp"
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
// TextView3 - Заголовок
|
||||||
|
Text(
|
||||||
|
text = "Авторизация",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// ImageView - Логотип
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.img5),
|
||||||
|
contentDescription = "logo",
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 20.dp)
|
||||||
|
.size(132.dp, 124.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// TextView - Метка "Имя пользователя"
|
||||||
|
Text(
|
||||||
|
text = "Имя пользователя",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// EditText - Поле ввода имени
|
||||||
|
// Используем Card для имитации @drawable/player_card_bg
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = Color.Transparent
|
||||||
|
),
|
||||||
|
border = ButtonDefaults.outlinedButtonBorder
|
||||||
|
) {
|
||||||
|
BasicTextField(
|
||||||
|
value = name,
|
||||||
|
onValueChange = onNameChange,
|
||||||
|
textStyle = TextStyle(
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
decorationBox = { innerTextField ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.Transparent)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
|
) {
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = "Введите имя",
|
||||||
|
color = Color(0xFF666666),
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontStyle = FontStyle.Italic
|
||||||
|
)
|
||||||
|
}
|
||||||
|
innerTextField()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.Transparent)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextView2 - Метка "Пароль"
|
||||||
|
Text(
|
||||||
|
text = "Пароль",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// EditText - Поле ввода пароля
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = Color.Transparent
|
||||||
|
),
|
||||||
|
border = ButtonDefaults.outlinedButtonBorder
|
||||||
|
) {
|
||||||
|
BasicTextField(
|
||||||
|
value = password,
|
||||||
|
onValueChange = onPasswordChange,
|
||||||
|
textStyle = TextStyle(
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
singleLine = true,
|
||||||
|
visualTransformation = PasswordVisualTransformation(),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
|
||||||
|
decorationBox = { innerTextField ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.Transparent)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
|
) {
|
||||||
|
if (password.isEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = "Введите пароль",
|
||||||
|
color = Color(0xFF666666),
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontStyle = FontStyle.Italic
|
||||||
|
)
|
||||||
|
}
|
||||||
|
innerTextField()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.Transparent)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// txtWarn - Текст ошибки
|
||||||
|
if (warningText.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = warningText,
|
||||||
|
color = Color(0xFFFF6B6B),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 5.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Индикатор загрузки или кнопки
|
||||||
|
if (isLoading) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.padding(top = 20.dp),
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// btnLogin - Кнопка входа
|
||||||
|
Button(
|
||||||
|
onClick = onLoginClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 30.dp)
|
||||||
|
.height(56.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color(0xFF2196F3)
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Войти",
|
||||||
|
fontSize = 24.sp,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// textView10 - Текст-подсказка
|
||||||
|
Text(
|
||||||
|
text = "Нет аккаунта? Зарегистрируйтесь!",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.width(371.dp)
|
||||||
|
.padding(top = 16.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// btnRegister - Кнопка регистрации
|
||||||
|
Button(
|
||||||
|
onClick = onRegisterClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 16.dp, bottom = 20.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color(0xFF4CAF50)
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Регистрация",
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция валидации (добавь, если её нет)
|
||||||
|
fun validateFields(name: String, password: String, context: Context): Boolean {
|
||||||
|
return when {
|
||||||
|
name.isBlank() -> {
|
||||||
|
Toast.makeText(context, "Введите имя пользователя", Toast.LENGTH_SHORT).show()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
password.isBlank() -> {
|
||||||
|
Toast.makeText(context, "Введите пароль", Toast.LENGTH_SHORT).show()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
|
||||||
private AuthManager authManager;
|
|
||||||
private EditText editTextName;
|
|
||||||
private EditText editTextPass;
|
|
||||||
private Button buttonSubmit;
|
|
||||||
private TextView textViewError;
|
|
||||||
|
|
||||||
private Button buttonReg;
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
// 1. Сначала проверяем сессию. Если вошел — уходим отсюда сразу.
|
|
||||||
SharedPreferences prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE);
|
|
||||||
if (prefs.getBoolean("isLoggedIn", false)) {
|
|
||||||
startActivity(new Intent(this, LoadScreen.class));
|
|
||||||
finish();
|
|
||||||
return; // Обязательно выходим из метода, чтобы не грузить Layout ниже
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Только если НЕ залогинен, инициализируем интерфейс
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
|
|
||||||
// 3. Инициализируем остальное
|
|
||||||
authManager = new AuthManager(this);
|
|
||||||
editTextName = findViewById(R.id.editTextText);
|
|
||||||
editTextPass = findViewById(R.id.editTextTextPassword2);
|
|
||||||
textViewError = findViewById(R.id.txtWarn);
|
|
||||||
buttonSubmit = findViewById(R.id.btnLogin);
|
|
||||||
buttonReg = findViewById(R.id.btnRegister);
|
|
||||||
buttonSubmit.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
checkFieldAndProceed();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonReg.setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(MainActivity.this, RegActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkFieldAndProceed() {
|
|
||||||
String name = editTextName.getText().toString().trim();
|
|
||||||
String password = editTextPass.getText().toString().trim();
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {
|
|
||||||
showErrorMessage("Поля не могут быть пустыми!");
|
|
||||||
} else {
|
|
||||||
hideErrorMessage();
|
|
||||||
|
|
||||||
// ВМЕСТО openSecondActivity(name) делаем запрос к серверу:
|
|
||||||
// false означает, что это попытка входа (Login)
|
|
||||||
authManager.authUser(name, password, "", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void showErrorMessage(String message) {
|
|
||||||
if (textViewError != null) {
|
|
||||||
textViewError.setText(message);
|
|
||||||
textViewError.setAlpha(1f);
|
|
||||||
textViewError.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
// Скрываем через 1 секунду
|
|
||||||
new android.os.Handler().postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
hideErrorMessage();
|
|
||||||
}
|
|
||||||
}, 1000); // 1000 миллисекунд = 1 секунда
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideErrorMessage() {
|
|
||||||
if (textViewError != null && textViewError.getVisibility() == View.VISIBLE) {
|
|
||||||
textViewError.animate()
|
|
||||||
.alpha(0f)
|
|
||||||
.setDuration(500) // Анимация скрытия 0.5 секунды
|
|
||||||
.withEndAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
textViewError.setVisibility(View.GONE);
|
|
||||||
textViewError.setAlpha(1f);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openSecondActivity(String realName) {
|
|
||||||
Intent intent = new Intent(MainActivity.this, LoadScreen.class);
|
|
||||||
intent.putExtra("USER_NAME", realName);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,357 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.*
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var apiService: MyApiService
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
// Простая структура без сложных вложений
|
||||||
|
MainScreenContent(
|
||||||
|
apiService = apiService,
|
||||||
|
onLogout = {
|
||||||
|
val prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE)
|
||||||
|
prefs.edit { clear() }
|
||||||
|
startActivity(Intent(this@MainActivity, LogActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MainScreenContent(
|
||||||
|
apiService: MyApiService,
|
||||||
|
onLogout: () -> Unit
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var players by remember { mutableStateOf<List<UserResponse>>(emptyList()) }
|
||||||
|
var isLoading by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
// Загружаем данные
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
try {
|
||||||
|
val response = apiService.getPlayers()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
players = response.body() ?: emptyList()
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
Toast.makeText(context, "Ошибка сети", Toast.LENGTH_SHORT).show()
|
||||||
|
} finally {
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Простой Box с фоном
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFF3E4B54))
|
||||||
|
) {
|
||||||
|
// Верхняя часть с кнопками
|
||||||
|
MainHeader(
|
||||||
|
onLogout = onLogout,
|
||||||
|
context = context
|
||||||
|
)
|
||||||
|
|
||||||
|
// Список игроков или индикатор загрузки
|
||||||
|
if (isLoading) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
PlayersList(
|
||||||
|
players = players,
|
||||||
|
context = context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MainHeader(
|
||||||
|
onLogout: () -> Unit,
|
||||||
|
context: Context
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color(0xFF3E4B54))
|
||||||
|
.padding(bottom = 16.dp)
|
||||||
|
) {
|
||||||
|
// Верхний ряд с меню и заголовком
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 16.dp, top = 16.dp, end = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// Кнопка меню
|
||||||
|
TopMenuButton(
|
||||||
|
modifier = Modifier.size(39.dp, 37.dp),
|
||||||
|
onLogout = onLogout
|
||||||
|
)
|
||||||
|
|
||||||
|
// Текст MySERVER
|
||||||
|
Text(
|
||||||
|
text = "MySERVER",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontStyle = FontStyle.Italic,
|
||||||
|
modifier = Modifier.padding(start = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
// Изображение img21
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.img21),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(width = 214.dp, height = 57.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Кнопки меню (Профиль, Карта мира, Информация)
|
||||||
|
MainMenuButtons(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 16.dp),
|
||||||
|
context = context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TopMenuButton(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onLogout: () -> Unit
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Box {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.img6),
|
||||||
|
contentDescription = "Menu",
|
||||||
|
modifier = modifier.clickable(
|
||||||
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
indication = null
|
||||||
|
) { expanded = true }
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false },
|
||||||
|
modifier = Modifier.background(Color(0xFF3E4B54))
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Выйти", color = Color.Red) },
|
||||||
|
onClick = {
|
||||||
|
expanded = false
|
||||||
|
onLogout()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MainMenuButtons(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
context: Context
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier,
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
|
) {
|
||||||
|
// Кнопка Профиль
|
||||||
|
MenuButton(
|
||||||
|
iconRes = R.drawable.img19,
|
||||||
|
backgroundRes = R.drawable.img16,
|
||||||
|
label = "Профиль",
|
||||||
|
onClick = {
|
||||||
|
context.startActivity(Intent(context, YourProfile::class.java))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Кнопка Карта мира
|
||||||
|
MenuButton(
|
||||||
|
iconRes = R.drawable.img18,
|
||||||
|
backgroundRes = R.drawable.img16,
|
||||||
|
label = "Карта мира",
|
||||||
|
onClick = {
|
||||||
|
context.startActivity(Intent(context, MapActivity::class.java))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Кнопка Информация
|
||||||
|
MenuButton(
|
||||||
|
iconRes = R.drawable.img22,
|
||||||
|
backgroundRes = R.drawable.img16,
|
||||||
|
label = "Информация",
|
||||||
|
onClick = {
|
||||||
|
context.startActivity(Intent(context, InformationActivity::class.java))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MenuButton(
|
||||||
|
iconRes: Int,
|
||||||
|
backgroundRes: Int,
|
||||||
|
label: String,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
modifier = Modifier.size(90.dp)
|
||||||
|
) {
|
||||||
|
// Фон
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = backgroundRes),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentScale = ContentScale.Fit
|
||||||
|
)
|
||||||
|
|
||||||
|
// Иконка
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = iconRes),
|
||||||
|
contentDescription = label,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(60.dp)
|
||||||
|
.clickable(
|
||||||
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
indication = null
|
||||||
|
) { onClick() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PlayersList(
|
||||||
|
players: List<UserResponse>,
|
||||||
|
context: Context
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(top = 210.dp) // Отступ для заголовка
|
||||||
|
.clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp))
|
||||||
|
.background(Color(0xFF2F4F4F)),
|
||||||
|
contentPadding = PaddingValues(16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
items(
|
||||||
|
items = players // Добавляем ключ для стабильности
|
||||||
|
) { player ->
|
||||||
|
PlayerCard(
|
||||||
|
player = player,
|
||||||
|
onClick = {
|
||||||
|
val intent = Intent(context, ProfileActivity::class.java).apply {
|
||||||
|
putExtra("PLAYER_NAME", player.realname ?: player.username)
|
||||||
|
}
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PlayerCard(
|
||||||
|
player: UserResponse,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable(
|
||||||
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
indication = null
|
||||||
|
) { onClick() },
|
||||||
|
shape = RoundedCornerShape(20.dp),
|
||||||
|
border = BorderStroke(2.dp, Color.LightGray),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = Color(0xFF3E4B54)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
player.realname?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = "Активен",
|
||||||
|
color = Color(0xFF4CAF50),
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "▶",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import retrofit2.Retrofit;
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
import java.util.List;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.animation.AlphaAnimation;
|
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity2 extends AppCompatActivity {
|
|
||||||
private RecyclerView rvPlayers;
|
|
||||||
private PlayerAdapter adapter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_main2);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
rvPlayers = findViewById(R.id.rvPlayers);
|
|
||||||
rvPlayers.setLayoutManager(new LinearLayoutManager(this));
|
|
||||||
|
|
||||||
loadPlayers();
|
|
||||||
|
|
||||||
ImageView image = findViewById(R.id.buttonMenu);
|
|
||||||
image.setOnClickListener(v -> {
|
|
||||||
PopupMenu popup = new PopupMenu(MainActivity2.this, v);
|
|
||||||
popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());
|
|
||||||
|
|
||||||
popup.setOnMenuItemClickListener(item -> {
|
|
||||||
if (item.getItemId() == R.id.option_2) {
|
|
||||||
//Intent intent = new Intent(MainActivity2.this, MainActivity3.class);
|
|
||||||
//startActivity(intent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (item.getItemId() == R.id.option1) {
|
|
||||||
getSharedPreferences("AppPrefs", MODE_PRIVATE).edit().clear().apply();
|
|
||||||
startActivity(new Intent(MainActivity2.this, MainActivity.class));
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
popup.show();
|
|
||||||
});
|
|
||||||
ImageView map = findViewById(R.id.imageButtonMap);
|
|
||||||
map.setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(MainActivity2.this, MapActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
|
|
||||||
ImageView player = findViewById(R.id.imageButtonPlayer);
|
|
||||||
player.setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(MainActivity2.this, MainActivity3.class);
|
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
ImageView inf = findViewById(R.id.imageButton);
|
|
||||||
inf.setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(MainActivity2.this, InformationActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private void loadPlayers() {
|
|
||||||
RetrofitClient.getApiService().getPlayers().enqueue(new Callback<List<UserResponse>>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(Call<List<UserResponse>> call, Response<List<UserResponse>> response) {
|
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
|
||||||
adapter = new PlayerAdapter(response.body(), player -> {
|
|
||||||
// ПЕРЕХОД В ПРОФИЛЬ
|
|
||||||
Intent intent = new Intent(MainActivity2.this, ProfileActivity.class);
|
|
||||||
intent.putExtra("PLAYER_NAME", player.getRealname());
|
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
rvPlayers.setAdapter(adapter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Call<List<UserResponse>> call, Throwable t) {
|
|
||||||
Toast.makeText(MainActivity2.this, "Ошибка списка", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
|
|
||||||
public class MainActivity3 extends AppCompatActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_main3);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
ImageView back = findViewById(R.id.imageButton4);
|
|
||||||
back.setOnClickListener(v -> {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import android.webkit.WebViewClient;
|
|
||||||
|
|
||||||
public class MapActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_map);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
WebView webView = findViewById(R.id.webView);
|
|
||||||
webView.getSettings().setJavaScriptEnabled(true);
|
|
||||||
webView.setWebViewClient(new WebViewClient());
|
|
||||||
webView.loadUrl("http://quantumblocks.hopto.org:8123");
|
|
||||||
ImageView back = findViewById(R.id.imageButton2);
|
|
||||||
back.setOnClickListener(v -> {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.webkit.WebResourceError
|
||||||
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebSettings
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class MapActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
MapScreen(
|
||||||
|
onBackClick = { finish() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MapScreen(
|
||||||
|
onBackClick: () -> Unit
|
||||||
|
) {
|
||||||
|
// Состояние для отслеживания загрузки
|
||||||
|
var isLoading by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
color = Color(0xFF3E4B54) // Фирменный фон
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
// WebView на весь экран (с отступами как в XML)
|
||||||
|
WebViewContent(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(horizontal = 2.dp) // android:layout_marginStart="2dp" и marginEnd="2dp"
|
||||||
|
.padding(top = 76.dp) //Отступ для тулбара (примерно height ImageButton + отступы)
|
||||||
|
.padding(bottom = 16.dp), // Немного отступа снизу
|
||||||
|
onLoadingStateChange = { loading -> isLoading = loading }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Верхняя панель (поверх WebView)
|
||||||
|
MapTopBar(
|
||||||
|
onBackClick = onBackClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Индикатор загрузки
|
||||||
|
if (isLoading) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFF3E4B54).copy(alpha = 0.7f)),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
color = Color.White,
|
||||||
|
strokeWidth = 4.dp,
|
||||||
|
modifier = Modifier.size(48.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(
|
||||||
|
text = "Загрузка карты...",
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MapTopBar(
|
||||||
|
onBackClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.background(Color(0xFF3E4B54).copy(alpha = 0.9f)) // Полупрозрачный фон
|
||||||
|
.padding(top = 16.dp)
|
||||||
|
) {
|
||||||
|
// Верхний ряд с кнопкой назад
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 16.dp, end = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// Кнопка назад (ImageButton из XML с @drawable/img9)
|
||||||
|
IconButton(
|
||||||
|
onClick = onBackClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
.padding(0.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.img9),
|
||||||
|
contentDescription = "Назад",
|
||||||
|
tint = Color.Unspecified // Сохраняем оригинальный цвет
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Пустое пространство для баланса
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Заголовок (TextView из XML)
|
||||||
|
Text(
|
||||||
|
text = "Карта режима Survival", // Исправлено "Surrvival" -> "Survival"
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 25.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
@Composable
|
||||||
|
fun WebViewContent(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onLoadingStateChange: (Boolean) -> Unit = {}
|
||||||
|
) {
|
||||||
|
AndroidView(
|
||||||
|
factory = { context ->
|
||||||
|
WebView(context).apply {
|
||||||
|
webViewClient = object : WebViewClient() {
|
||||||
|
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
|
||||||
|
super.onReceivedError(view, request, error)
|
||||||
|
android.util.Log.e("WebView", "Error: ${error?.description}")
|
||||||
|
}
|
||||||
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
|
super.onPageFinished(view, url)
|
||||||
|
onLoadingStateChange(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageStarted(view: WebView?, url: String?, favicon: android.graphics.Bitmap?) {
|
||||||
|
super.onPageStarted(view, url, favicon)
|
||||||
|
onLoadingStateChange(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.apply {
|
||||||
|
javaScriptEnabled = true
|
||||||
|
loadWithOverviewMode = true
|
||||||
|
useWideViewPort = true
|
||||||
|
builtInZoomControls = true
|
||||||
|
displayZoomControls = false
|
||||||
|
domStorageEnabled = true
|
||||||
|
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW// Для современных карт
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загружаем URL карты
|
||||||
|
loadUrl("http://quantumblocks.hopto.org:8123/")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Предпросмотр для разработки
|
||||||
|
@Composable
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
fun MapScreenPreview() {
|
||||||
|
MaterialTheme {
|
||||||
|
MapScreen(
|
||||||
|
onBackClick = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.http.Body;
|
|
||||||
import retrofit2.http.POST;
|
|
||||||
import retrofit2.http.GET;
|
|
||||||
import java.util.List;
|
|
||||||
public interface MyApiService {
|
|
||||||
@POST("api/auth/login")
|
|
||||||
Call<UserResponse> login(@Body UserRequest request);
|
|
||||||
|
|
||||||
@POST("api/auth/register")
|
|
||||||
Call<UserResponse> register(@Body UserRequest request);
|
|
||||||
|
|
||||||
@GET("api/auth/players") // Тот же путь, что на сервере
|
|
||||||
Call<List<UserResponse>> getPlayers();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.POST
|
||||||
|
|
||||||
|
interface MyApiService {
|
||||||
|
|
||||||
|
@POST("api/auth/login")
|
||||||
|
suspend fun login(@Body request: UserRequest): Response<UserResponse>
|
||||||
|
|
||||||
|
@POST("api/auth/register")
|
||||||
|
suspend fun register(@Body request: UserRequest): Response<UserResponse>
|
||||||
|
|
||||||
|
@GET("api/auth/players")
|
||||||
|
suspend fun getPlayers(): Response<List<UserResponse>>
|
||||||
|
|
||||||
|
@POST("api/auth/update")
|
||||||
|
suspend fun updateUser(@Body request: UserRequest): Response<UserResponse>
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
|
||||||
|
@HiltAndroidApp
|
||||||
|
class MyApplication : Application()
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class) // ИСПРАВЛЕНО: ::class вместо .class
|
||||||
|
object NetworkModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideApiService(): MyApiService {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl("http://quantumblocks.hopto.org:45678") // Твой URL со слэшем на конце
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
.create(MyApiService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.ViewHolder> {
|
|
||||||
|
|
||||||
private List<UserResponse> playerList;
|
|
||||||
private OnPlayerClickListener listener;
|
|
||||||
|
|
||||||
// Интерфейс для клика
|
|
||||||
public interface OnPlayerClickListener {
|
|
||||||
void onPlayerClick(UserResponse player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayerAdapter(List<UserResponse> playerList, OnPlayerClickListener listener) {
|
|
||||||
this.playerList = playerList;
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_player, parent, false);
|
|
||||||
return new ViewHolder(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
|
||||||
UserResponse player = playerList.get(position);
|
|
||||||
holder.tvName.setText(player.getRealname());
|
|
||||||
|
|
||||||
// Клик по прямоугольнику
|
|
||||||
holder.itemView.setOnClickListener(v -> listener.onPlayerClick(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() { return playerList.size(); }
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
TextView tvName;
|
|
||||||
public ViewHolder(View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
tvName = itemView.findViewById(R.id.tvName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
public class ProfileActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_profile);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
ImageView back = findViewById(R.id.imageButton2);
|
|
||||||
back.setOnClickListener(v -> {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.BorderStroke
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class ProfileActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// Получаем имя игрока, которое передали из списка
|
||||||
|
val playerName = intent.getStringExtra("PLAYER_NAME") ?: "Неизвестный игрок"
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
// Важно: MaterialTheme должен быть корневым
|
||||||
|
MaterialTheme {
|
||||||
|
ViewProfileScreen(
|
||||||
|
name = playerName,
|
||||||
|
onBackClick = { finish() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ViewProfileScreen(
|
||||||
|
name: String,
|
||||||
|
onBackClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
color = Color(0xFF3E4B54) // Фирменный фон
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
// Верхняя панель с кнопкой назад и заголовком
|
||||||
|
ProfileTopBar(
|
||||||
|
onBackClick = onBackClick
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
// Заголовок (можно убрать, если он уже есть в TopBar)
|
||||||
|
Text(
|
||||||
|
text = "Профиль игрока",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 28.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(bottom = 32.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Карточка с именем (в твоем стиле с белой обводкой)
|
||||||
|
InfoCard(
|
||||||
|
label = "Игровой ник",
|
||||||
|
value = name
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Карточка со статусом
|
||||||
|
InfoCard(
|
||||||
|
label = "Статус",
|
||||||
|
value = "В игре"
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Карточка с информацией
|
||||||
|
InfoCard(
|
||||||
|
label = "Ранг",
|
||||||
|
value = "Игрок"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Добавим немного места внизу для красоты
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ProfileTopBar(
|
||||||
|
onBackClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBackClick,
|
||||||
|
modifier = Modifier.size(48.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowBack,
|
||||||
|
contentDescription = "Назад",
|
||||||
|
tint = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Информация об игроке",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
modifier = Modifier.padding(start = 8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InfoCard(
|
||||||
|
label: String,
|
||||||
|
value: String
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
shape = RoundedCornerShape(20.dp),
|
||||||
|
border = BorderStroke(2.dp, Color.White),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = Color(0xFF3E4B54)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(20.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.LightGray,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = value,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(top = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Предпросмотр для разработки
|
||||||
|
@Composable
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
fun ViewProfileScreenPreview() {
|
||||||
|
MaterialTheme {
|
||||||
|
ViewProfileScreen(
|
||||||
|
name = "Steve",
|
||||||
|
onBackClick = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.graphics.Insets;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
public class RegActivity extends AppCompatActivity {
|
|
||||||
private AuthManager authManager;
|
|
||||||
private EditText editTextName;
|
|
||||||
private EditText editTextPass;
|
|
||||||
private EditText editTextEmail;
|
|
||||||
private Button buttonSubmit;
|
|
||||||
private TextView textViewError;
|
|
||||||
private Button buttonReg;
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_reg_activity);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
editTextName = findViewById(R.id.editTextText);
|
|
||||||
editTextEmail = findViewById(R.id.editTextEmail);
|
|
||||||
editTextPass = findViewById(R.id.editTextTextPassword2);
|
|
||||||
textViewError = findViewById(R.id.txtWarn);
|
|
||||||
buttonSubmit = findViewById(R.id.btnRegister);
|
|
||||||
buttonSubmit.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
checkFieldAndProceed();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
authManager = new AuthManager(this); // 2. Инициализируем
|
|
||||||
buttonReg = findViewById(R.id.btnLogin);
|
|
||||||
buttonReg.setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(RegActivity.this, MainActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkFieldAndProceed() {
|
|
||||||
String name = editTextName.getText().toString().trim();
|
|
||||||
String password = editTextPass.getText().toString().trim();
|
|
||||||
String email = editTextEmail.getText().toString().trim();
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password) || TextUtils.isEmpty(email)) {
|
|
||||||
showErrorMessage("Поля не могут быть пустыми!");
|
|
||||||
} else {
|
|
||||||
hideErrorMessage();
|
|
||||||
|
|
||||||
// 3. ВМЕСТО openSecondActivity и finish() вызываем сервер:
|
|
||||||
// true означает, что это РЕГИСТРАЦИЯ
|
|
||||||
authManager.authUser(name, password, email, true);
|
|
||||||
|
|
||||||
// ПРИМЕЧАНИЕ: finish() делать ТУТ НЕ НУЖНО.
|
|
||||||
// AuthManager сам сделает переход и закроет экран при успешном ответе.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showErrorMessage(String message) {
|
|
||||||
if (textViewError != null) {
|
|
||||||
textViewError.setText(message);
|
|
||||||
textViewError.setAlpha(1f);
|
|
||||||
textViewError.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
// Скрываем через 1 секунду
|
|
||||||
new android.os.Handler().postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
hideErrorMessage();
|
|
||||||
}
|
|
||||||
}, 1000); // 1000 миллисекунд = 1 секунда
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideErrorMessage() {
|
|
||||||
if (textViewError != null && textViewError.getVisibility() == View.VISIBLE) {
|
|
||||||
textViewError.animate()
|
|
||||||
.alpha(0f)
|
|
||||||
.setDuration(500) // Анимация скрытия 0.5 секунды
|
|
||||||
.withEndAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
textViewError.setVisibility(View.GONE);
|
|
||||||
textViewError.setAlpha(1f);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openSecondActivity(String realName) {
|
|
||||||
Intent intent = new Intent(RegActivity.this, LoadScreen.class);
|
|
||||||
intent.putExtra("USER_NAME", realName);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,355 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Patterns
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class RegActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
RegistrationScreen(
|
||||||
|
onNavigateToLogin = {
|
||||||
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RegistrationScreen(
|
||||||
|
viewModel: AuthViewModel = viewModel(),
|
||||||
|
onNavigateToLogin: () -> Unit
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var name by remember { mutableStateOf("") }
|
||||||
|
var email by remember { mutableStateOf("") }
|
||||||
|
var password by remember { mutableStateOf("") }
|
||||||
|
var warningText by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
val authState by viewModel.authState.collectAsState()
|
||||||
|
|
||||||
|
// Слушатель состояния регистрации
|
||||||
|
LaunchedEffect(authState) {
|
||||||
|
when (authState) {
|
||||||
|
is AuthState.Success -> {
|
||||||
|
Toast.makeText(context, "Успешная регистрация!", Toast.LENGTH_SHORT).show()
|
||||||
|
onNavigateToLogin()
|
||||||
|
}
|
||||||
|
is AuthState.Error -> {
|
||||||
|
warningText = (authState as AuthState.Error).message
|
||||||
|
}
|
||||||
|
else -> { /* Loading or Idle */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScrollView аналог с фоном
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFF3E4B54)) // android:background="#3E4B54"
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
// LinearLayout аналог с padding
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp), // android:padding="16dp"
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
// Заголовок "Регистрация" (textView3)
|
||||||
|
Text(
|
||||||
|
text = "Регистрация",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// Метка "Придумайте имя" (textView)
|
||||||
|
Text(
|
||||||
|
text = "Придумайте имя",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// Поле ввода имени (editTextText)
|
||||||
|
CustomTextField(
|
||||||
|
value = name,
|
||||||
|
onValueChange = {
|
||||||
|
name = it
|
||||||
|
warningText = ""
|
||||||
|
},
|
||||||
|
placeholder = "Введите имя",
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Метка "Придумайте пароль" (textView2)
|
||||||
|
Text(
|
||||||
|
text = "Придумайте пароль",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// Поле ввода пароля (editTextTextPassword2)
|
||||||
|
CustomTextField(
|
||||||
|
value = password,
|
||||||
|
onValueChange = {
|
||||||
|
password = it
|
||||||
|
warningText = ""
|
||||||
|
},
|
||||||
|
placeholder = "Введите пароль",
|
||||||
|
isPassword = true,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Метка "E-mail" (textView9)
|
||||||
|
Text(
|
||||||
|
text = "E-mail",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// Поле ввода email (editTextEmail)
|
||||||
|
CustomTextField(
|
||||||
|
value = email,
|
||||||
|
onValueChange = {
|
||||||
|
email = it
|
||||||
|
warningText = ""
|
||||||
|
},
|
||||||
|
placeholder = "Введите почту",
|
||||||
|
keyboardType = KeyboardType.Email,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Текст ошибки (txtWarn)
|
||||||
|
if (warningText.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = warningText,
|
||||||
|
color = Color(0xFFFF6B6B),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 5.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authState is AuthState.Loading) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.padding(top = 20.dp),
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Кнопка регистрации (btnRegister)
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
if (validateRegFields(name, email, password, context,
|
||||||
|
onError = { warningText = it }
|
||||||
|
)) {
|
||||||
|
viewModel.authUser(
|
||||||
|
UserRequest(username = name, password = password, email = email),
|
||||||
|
isRegistration = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 16.dp, bottom = 20.dp)
|
||||||
|
.height(56.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color(0xFF4CAF50) // Зеленый цвет из XML
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Зарегистрироваться", // Исправил опечатку "Зарегестрироваться"
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Текст-подсказка (textView11)
|
||||||
|
Text(
|
||||||
|
text = "Уже есть аккаунт? Войдите!",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// Кнопка входа (btnLogin)
|
||||||
|
Button(
|
||||||
|
onClick = onNavigateToLogin,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp)
|
||||||
|
.padding(top = 16.dp, bottom = 20.dp)
|
||||||
|
.height(56.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color(0xFF2196F3) // Синий цвет из XML
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Войти",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 24.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CustomTextField(
|
||||||
|
value: String,
|
||||||
|
onValueChange: (String) -> Unit,
|
||||||
|
placeholder: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
isPassword: Boolean = false,
|
||||||
|
keyboardType: KeyboardType = KeyboardType.Text
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = modifier,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = Color.Transparent
|
||||||
|
),
|
||||||
|
border = ButtonDefaults.outlinedButtonBorder
|
||||||
|
) {
|
||||||
|
BasicTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
textStyle = TextStyle(
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
singleLine = true,
|
||||||
|
visualTransformation = if (isPassword) PasswordVisualTransformation() else VisualTransformation.None,
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = keyboardType),
|
||||||
|
decorationBox = { innerTextField ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.Transparent)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
|
) {
|
||||||
|
if (value.isEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = placeholder,
|
||||||
|
color = Color(0xFF666666), // android:textColorHint="#666666"
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontStyle = FontStyle.Italic // android:textStyle="italic"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
innerTextField()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.Transparent)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateRegFields(
|
||||||
|
name: String,
|
||||||
|
email: String,
|
||||||
|
pass: String,
|
||||||
|
context: Context,
|
||||||
|
onError: (String) -> Unit
|
||||||
|
): Boolean {
|
||||||
|
if (name.isEmpty() || pass.isEmpty() || email.isEmpty()) {
|
||||||
|
onError("Заполните все поля!")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (name.length !in 3..16) {
|
||||||
|
onError("Имя должно быть от 3 до 16 символов")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (pass.length < 8) {
|
||||||
|
onError("Пароль должен быть минимум 8 символов")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
|
||||||
|
onError("Некорректный Email")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Предпросмотр для разработки
|
||||||
|
@Composable
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
fun RegistrationScreenPreview() {
|
||||||
|
MaterialTheme {
|
||||||
|
RegistrationScreen(
|
||||||
|
onNavigateToLogin = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
import retrofit2.Retrofit;
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory;
|
|
||||||
|
|
||||||
public class RetrofitClient {
|
|
||||||
private static Retrofit retrofit = null;
|
|
||||||
private static final String BASE_URL = "http://quantumblocks.hopto.org:45678/";
|
|
||||||
|
|
||||||
public static MyApiService getApiService() {
|
|
||||||
if (retrofit == null) {
|
|
||||||
retrofit = new Retrofit.Builder()
|
|
||||||
.baseUrl(BASE_URL)
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
return retrofit.create(MyApiService.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
// Модель для отправки данных (Login/Register)
|
||||||
|
data class UserRequest(
|
||||||
|
val username: String,
|
||||||
|
val password: String,
|
||||||
|
val email: String? = null // Опционально для регистрации
|
||||||
|
)
|
||||||
|
|
||||||
|
// Модель для получения данных от сервера
|
||||||
|
data class UserResponse(
|
||||||
|
val id: Long,
|
||||||
|
val username: String,
|
||||||
|
val realname: String? = null,
|
||||||
|
val email: String? = null
|
||||||
|
)
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
public class UserRequest {
|
|
||||||
private String realname;
|
|
||||||
private String password;
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
public UserRequest(String realname, String password, String email) {
|
|
||||||
this.realname = realname;
|
|
||||||
this.password = password;
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRealname() { return realname; }
|
|
||||||
public void setRealname(String realname) { this.realname = realname; }
|
|
||||||
public String getPassword() { return password; }
|
|
||||||
public void setPassword(String password) { this.password = password; }
|
|
||||||
public String getEmail() { return email; }
|
|
||||||
public void setEmail(String email) { this.email = email; }
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.example.myserver;
|
|
||||||
|
|
||||||
|
|
||||||
public class UserResponse {
|
|
||||||
private Long id;
|
|
||||||
private String realname;
|
|
||||||
|
|
||||||
public UserResponse() {}
|
|
||||||
|
|
||||||
public Long getId() { return id; }
|
|
||||||
public String getRealname() { return realname; }
|
|
||||||
public void setRealname(String realname) { this.realname = realname; }
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
package com.example.myserver
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.BorderStroke
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class YourProfile : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
MaterialTheme {
|
||||||
|
ProfileScreen(
|
||||||
|
onBackClick = { finish() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ProfileScreen(
|
||||||
|
onBackClick: () -> Unit
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val prefs = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
// Состояния полей (подтягиваем из памяти)
|
||||||
|
var name by remember { mutableStateOf(prefs.getString("realname", "") ?: "") }
|
||||||
|
var email by remember { mutableStateOf(prefs.getString("email", "") ?: "") }
|
||||||
|
var password by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
// Состояние для отслеживания сохранения
|
||||||
|
var isSaving by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
color = Color(0xFF3E4B54)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
// Кнопка назад
|
||||||
|
IconButton(
|
||||||
|
onClick = onBackClick,
|
||||||
|
modifier = Modifier.size(48.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowBack,
|
||||||
|
contentDescription = "Назад",
|
||||||
|
tint = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Ваш профиль",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 28.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(vertical = 24.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Поле Имя
|
||||||
|
ProfileTextField(
|
||||||
|
value = name,
|
||||||
|
label = "Имя в игре",
|
||||||
|
onValueChange = { name = it }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Поле Email
|
||||||
|
ProfileTextField(
|
||||||
|
value = email,
|
||||||
|
label = "Электронная почта",
|
||||||
|
onValueChange = { email = it }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Поле Пароль
|
||||||
|
ProfileTextField(
|
||||||
|
value = password,
|
||||||
|
label = "Новый пароль (оставьте пустым)",
|
||||||
|
onValueChange = { password = it },
|
||||||
|
isPassword = true
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
// Кнопка сохранения
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
isSaving = true
|
||||||
|
// Сохраняем в SharedPreferences
|
||||||
|
prefs.edit {
|
||||||
|
putString("realname", name)
|
||||||
|
if (email.isNotBlank()) {
|
||||||
|
putString("email", email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Toast.makeText(context, "Данные обновлены!", Toast.LENGTH_SHORT).show()
|
||||||
|
isSaving = false
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(56.dp),
|
||||||
|
shape = RoundedCornerShape(20.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color.White,
|
||||||
|
disabledContainerColor = Color.White.copy(alpha = 0.5f)
|
||||||
|
),
|
||||||
|
border = BorderStroke(2.dp, Color.LightGray),
|
||||||
|
enabled = !isSaving
|
||||||
|
) {
|
||||||
|
if (isSaving) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
color = Color(0xFF3E4B54),
|
||||||
|
strokeWidth = 2.dp
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = "СОХРАНИТЬ ИЗМЕНЕНИЯ",
|
||||||
|
color = Color(0xFF3E4B54),
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ProfileTextField(
|
||||||
|
value: String,
|
||||||
|
label: String,
|
||||||
|
onValueChange: (String) -> Unit,
|
||||||
|
isPassword: Boolean = false
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
label = {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.LightGray
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
textStyle = LocalTextStyle.current.copy(
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
colors = OutlinedTextFieldDefaults.colors( // ← Исправлено: используем OutlinedTextFieldDefaults
|
||||||
|
focusedBorderColor = Color.White,
|
||||||
|
unfocusedBorderColor = Color.White,
|
||||||
|
focusedTextColor = Color.White,
|
||||||
|
unfocusedTextColor = Color.White,
|
||||||
|
cursorColor = Color.White,
|
||||||
|
focusedLabelColor = Color.LightGray,
|
||||||
|
unfocusedLabelColor = Color.LightGray
|
||||||
|
),
|
||||||
|
visualTransformation = if (isPassword) PasswordVisualTransformation() else VisualTransformation.None,
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,74 +1,74 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector
|
<vector
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:viewportHeight="108"
|
android:viewportHeight="108"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<path android:fillColor="#3DDC84"
|
<path android:fillColor="#3DDC84"
|
||||||
android:pathData="M0,0h108v108h-108z"/>
|
android:pathData="M0,0h108v108h-108z"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<solid android:color="#3E4B54" /> <!-- Фон карточки -->
|
|
||||||
<stroke
|
|
||||||
android:width="2dp"
|
|
||||||
android:color="#FFFFFF" /> <!-- Белая обводка -->
|
|
||||||
<corners android:radius="20dp" /> <!-- Скругление углов -->
|
|
||||||
</shape>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#3E4B54"
|
|
||||||
tools:context=".InformationActivity">
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#3E4B54"
|
|
||||||
tools:context=".InformationActivity">
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/progressBar"
|
|
||||||
style="?android:attr/progressBarStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textLoading"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="Загрузка..."
|
|
||||||
android:textColor="#888888"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/progressBar" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textWelcome"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="50dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text=""
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:fillViewport="true"
|
|
||||||
android:background="#3E4B54">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView3"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Авторизация"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imageView"
|
|
||||||
android:layout_width="132dp"
|
|
||||||
android:layout_height="124dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:contentDescription="logo"
|
|
||||||
android:src="@drawable/img5" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Имя пользователя"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editTextText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:autofillHints="username"
|
|
||||||
android:background="@drawable/player_card_bg"
|
|
||||||
android:hint="Введите имя"
|
|
||||||
android:inputType="textPersonName"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textColorHint="#666666"
|
|
||||||
android:textStyle="italic" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Пароль"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editTextTextPassword2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:autofillHints="password"
|
|
||||||
android:background="@drawable/player_card_bg"
|
|
||||||
android:hint="Введите пароль"
|
|
||||||
android:inputType="textPassword"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textColorHint="#666666"
|
|
||||||
android:textStyle="italic" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtWarn"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text=""
|
|
||||||
android:textColor="#FF6B6B"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnLogin"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="30dp"
|
|
||||||
android:backgroundTint="#2196F3"
|
|
||||||
android:text="Войти"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView10"
|
|
||||||
android:layout_width="371dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Нет аккаунта? Зарегестрируйтесь!"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnRegister"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="20dp"
|
|
||||||
android:backgroundTint="#4CAF50"
|
|
||||||
android:text="Регистрация"
|
|
||||||
android:textColor="#FFFFFF" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#3E4B54"
|
|
||||||
tools:context=".MainActivity2">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/buttonMenu"
|
|
||||||
android:layout_width="39dp"
|
|
||||||
android:layout_height="37dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:contentDescription="@string/image_view_description"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="0.0"
|
|
||||||
app:srcCompat="@drawable/img6" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/rvPlayers"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:background="@drawable/player_card_bg"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/textView5" />
|
|
||||||
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/imageButtonPlayer"
|
|
||||||
android:layout_width="102dp"
|
|
||||||
android:layout_height="97dp"
|
|
||||||
android:layout_marginStart="22dp"
|
|
||||||
android:layout_marginTop="64dp"
|
|
||||||
android:backgroundTint="#00FFFFFF"
|
|
||||||
android:contentDescription="@string/image_view_description3"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img19"
|
|
||||||
tools:srcCompat="@drawable/img19" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/imageButtonMap"
|
|
||||||
android:layout_width="71dp"
|
|
||||||
android:layout_height="67dp"
|
|
||||||
android:layout_marginStart="155dp"
|
|
||||||
android:layout_marginTop="80dp"
|
|
||||||
android:layout_marginEnd="156dp"
|
|
||||||
android:backgroundTint="#00FFFFFF"
|
|
||||||
android:contentDescription="@string/image_view_description4"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.517"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img18"
|
|
||||||
tools:srcCompat="@drawable/img18" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView5"
|
|
||||||
android:layout_width="77dp"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:layout_marginStart="167dp"
|
|
||||||
android:layout_marginTop="162dp"
|
|
||||||
android:layout_marginEnd="167dp"
|
|
||||||
android:background="#00FFFFFF"
|
|
||||||
android:drawableTint="#FFFFFF"
|
|
||||||
android:foregroundTint="#F7FFFFFF"
|
|
||||||
android:text="Карта мира"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView6"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="44dp"
|
|
||||||
android:layout_marginTop="162dp"
|
|
||||||
android:text="Профиль"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/imageButton"
|
|
||||||
android:layout_width="97dp"
|
|
||||||
android:layout_height="105dp"
|
|
||||||
android:layout_marginTop="64dp"
|
|
||||||
android:layout_marginEnd="22dp"
|
|
||||||
android:backgroundTint="#00FFFFFF"
|
|
||||||
android:contentDescription="@string/image_view_description6"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img22"
|
|
||||||
tools:srcCompat="@drawable/img22" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imageView2"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="64dp"
|
|
||||||
android:contentDescription="@string/image_view_description7"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/imageButton"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img16" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imageView3"
|
|
||||||
android:layout_width="99dp"
|
|
||||||
android:layout_height="97dp"
|
|
||||||
android:layout_marginTop="64dp"
|
|
||||||
android:contentDescription="@string/image_view_description8"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/imageButtonMap"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/imageButtonMap"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img16" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imageView4"
|
|
||||||
android:layout_width="102dp"
|
|
||||||
android:layout_height="96dp"
|
|
||||||
android:contentDescription="@string/image_view_description9"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/imageButtonPlayer"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/imageButtonPlayer"
|
|
||||||
app:srcCompat="@drawable/img16" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView7"
|
|
||||||
android:layout_width="91dp"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:layout_marginTop="162dp"
|
|
||||||
android:layout_marginEnd="22dp"
|
|
||||||
android:text="Информация"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView8"
|
|
||||||
android:layout_width="80dp"
|
|
||||||
android:layout_height="21dp"
|
|
||||||
android:layout_marginStart="64dp"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:text="MySERVER"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imageView5"
|
|
||||||
android:layout_width="214dp"
|
|
||||||
android:layout_height="57dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img21" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#3E4B54"
|
|
||||||
android:visibility="visible"
|
|
||||||
tools:context=".MainActivity3"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="409dp"
|
|
||||||
android:layout_height="804dp"
|
|
||||||
android:layout_marginStart="1dp"
|
|
||||||
android:layout_marginTop="86dp"
|
|
||||||
android:layout_marginEnd="1dp"
|
|
||||||
android:layout_marginBottom="1dp"
|
|
||||||
android:contentDescription="@string/image_view_description2"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical" />
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/imageButton4"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:contentDescription="@string/description1"
|
|
||||||
android:backgroundTint="#00FFFFFF"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img9" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#3E4B54"
|
|
||||||
tools:context=".MapActivity">
|
|
||||||
|
|
||||||
<WebView
|
|
||||||
android:id="@+id/webView"
|
|
||||||
android:layout_width="355dp"
|
|
||||||
android:layout_height="752dp"
|
|
||||||
android:layout_marginStart="2dp"
|
|
||||||
android:layout_marginEnd="2dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
|
|
||||||
</WebView>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/imageButton2"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_x="-4dp"
|
|
||||||
android:layout_y="61dp"
|
|
||||||
android:backgroundTint="#00FFFFFF"
|
|
||||||
android:contentDescription="@string/image_view_description5"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img9" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView4"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="67dp"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:layout_marginEnd="67dp"
|
|
||||||
android:text="Карта режима Surrvival"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="25sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#3E4B54"
|
|
||||||
tools:context=".MapActivity">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/imageButton2"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_x="-4dp"
|
|
||||||
android:layout_y="61dp"
|
|
||||||
android:backgroundTint="#00FFFFFF"
|
|
||||||
android:contentDescription="@string/image_view_description5"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/img9" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com"
|
|
||||||
android:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:fillViewport="true"
|
|
||||||
android:background="#3E4B54">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView3"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Регистрация"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Придумайте имя"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editTextText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:autofillHints="username"
|
|
||||||
android:background="@drawable/player_card_bg"
|
|
||||||
android:hint="Введите имя"
|
|
||||||
android:inputType="textPersonName"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textColorHint="#666666"
|
|
||||||
android:textStyle="italic" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Придумайте пароль"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editTextTextPassword2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:autofillHints="password"
|
|
||||||
android:background="@drawable/player_card_bg"
|
|
||||||
android:hint="Введите пароль"
|
|
||||||
android:inputType="textPassword"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textColorHint="#666666"
|
|
||||||
android:textStyle="italic" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView9"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="E-mail"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editTextEmail"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:autofillHints="email"
|
|
||||||
android:background="@drawable/player_card_bg"
|
|
||||||
android:hint="Введите почту"
|
|
||||||
android:inputType="textEmailAddress"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textColorHint="#666666"
|
|
||||||
android:textStyle="italic" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtWarn"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text=""
|
|
||||||
android:textColor="#FF6B6B"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnRegister"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="20dp"
|
|
||||||
android:backgroundTint="#4CAF50"
|
|
||||||
android:text="Зарегестрироваться"
|
|
||||||
android:textColor="#FFFFFF" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView11"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Уже есть аккаунт? Войдите!"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnLogin"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="50dp"
|
|
||||||
android:layout_marginTop="30dp"
|
|
||||||
android:backgroundTint="#2196F3"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Войти"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
app:cardCornerRadius="20dp"
|
|
||||||
app:cardElevation="4dp"
|
|
||||||
app:cardBackgroundColor="@android:color/transparent"> <!-- Прозрачный фон, чтобы видеть обводку из drawable -->
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:background="@drawable/player_card_bg"> <!-- Твоя обводка и фон здесь -->
|
|
||||||
|
|
||||||
<!-- Иконка головы -->
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgAvatar"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:src="@android:drawable/ic_menu_myplaces" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="PlayerName"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvStatus"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Активен"
|
|
||||||
android:textColor="#4CAF50"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@android:drawable/ic_media_play"
|
|
||||||
app:tint="#FFFFFF" /> <!-- Делаем стрелочку белой -->
|
|
||||||
</LinearLayout>
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/option_2"
|
|
||||||
android:icon="@drawable/img7"
|
|
||||||
android:iconTint="@color/black"
|
|
||||||
android:title="Настройки" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/option1"
|
|
||||||
android:title="Выйти"
|
|
||||||
android:iconTint="@color/black"/>
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
+6
-2
@@ -1,4 +1,8 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all subprojects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
}
|
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
|
||||||
|
id("com.google.dagger.hilt.android") version "2.51.1" apply false
|
||||||
|
id("org.jetbrains.kotlin.kapt") version "1.9.0" apply false
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+12
-1
@@ -6,7 +6,18 @@
|
|||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
|
||||||
|
--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
|
||||||
|
|
||||||
|
# ???????? ??????????????? ?????????? (???????? ??? ??????? kapt)
|
||||||
|
kapt.incremental.apt=true
|
||||||
|
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. For more details, visit
|
# This option should only be used with decoupled projects. For more details, visit
|
||||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||||
|
|||||||
+38
-21
@@ -1,32 +1,49 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.13.2"
|
agp = "8.13.2"
|
||||||
|
kotlin = "1.9.0"
|
||||||
|
hilt = "2.51.1"
|
||||||
|
composeBom = "2023.10.01"
|
||||||
|
retrofit = "2.9.0"
|
||||||
|
okhttp = "4.12.0"
|
||||||
|
activityCompose = "1.8.2"
|
||||||
|
lifecycle = "2.7.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.3.0"
|
junitVersion = "1.1.5"
|
||||||
espressoCore = "3.7.0"
|
espressoCore = "3.5.1"
|
||||||
appcompat = "1.7.1"
|
appcompat = "1.6.1"
|
||||||
material = "1.13.0"
|
material = "1.11.0"
|
||||||
activity = "1.12.2"
|
foundation = "1.10.4"
|
||||||
constraintlayout = "2.2.1"
|
|
||||||
recyclerview = "1.4.0"
|
|
||||||
cardview = "1.0.0"
|
|
||||||
viewpager2 = "1.1.0"
|
|
||||||
legacySupportV4 = "1.0.0"
|
|
||||||
mediarouter = "1.8.1"
|
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||||
|
# Compose
|
||||||
|
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||||
|
compose-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||||
|
compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||||
|
compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||||
|
compose-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||||
|
activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||||
|
lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
|
||||||
|
|
||||||
|
# Hilt (Dagger)
|
||||||
|
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
|
||||||
|
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
|
||||||
|
|
||||||
|
# Network (Retrofit)
|
||||||
|
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
|
||||||
|
retrofit-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
|
||||||
|
okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
|
||||||
|
|
||||||
|
# Standard
|
||||||
|
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundation" }
|
||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
|
||||||
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
|
||||||
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
|
||||||
recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
|
|
||||||
cardview = { group = "androidx.cardview", name = "cardview", version.ref = "cardview" }
|
|
||||||
viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2" }
|
|
||||||
legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
|
|
||||||
mediarouter = { group = "androidx.mediarouter", name = "mediarouter", version.ref = "mediarouter" }
|
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
|
||||||
|
kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
|
||||||
|
|||||||
+8
-8
@@ -1,8 +1,8 @@
|
|||||||
#Fri Feb 13 00:54:26 MSK 2026
|
#Fri Feb 13 00:54:26 MSK 2026
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Vendored
+94
-94
@@ -1,94 +1,94 @@
|
|||||||
@rem
|
@rem
|
||||||
@rem Copyright 2015 the original author or authors.
|
@rem Copyright 2015 the original author or authors.
|
||||||
@rem
|
@rem
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@rem you may not use this file except in compliance with the License.
|
@rem you may not use this file except in compliance with the License.
|
||||||
@rem You may obtain a copy of the License at
|
@rem You may obtain a copy of the License at
|
||||||
@rem
|
@rem
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@rem
|
@rem
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
@rem SPDX-License-Identifier: Apache-2.0
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
@rem This is normally unused
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
exit /b %EXIT_CODE%
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
|||||||
Reference in New Issue
Block a user