first commit

This commit is contained in:
MiDupl1711
2026-03-07 22:32:39 +03:00
commit b1d7efc034
99 changed files with 2429 additions and 0 deletions
@@ -0,0 +1,61 @@
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,26 @@
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,75 @@
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,123 @@
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,117 @@
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();
}
});
}
}
@@ -0,0 +1,33 @@
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();
});
}
}
@@ -0,0 +1,37 @@
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,17 @@
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,53 @@
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);
}
}
}
@@ -0,0 +1,30 @@
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,112 @@
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,18 @@
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,20 @@
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; }
}
@@ -0,0 +1,13 @@
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; }
}