nextNoteVault #23
@ -41,9 +41,13 @@ dependencies {
 | 
			
		||||
    implementation(libs.navigation.fragment)
 | 
			
		||||
    implementation(libs.navigation.ui)
 | 
			
		||||
    implementation(libs.room.runtime)
 | 
			
		||||
    implementation(libs.annotation)
 | 
			
		||||
    testImplementation(libs.junit)
 | 
			
		||||
    androidTestImplementation(libs.ext.junit)
 | 
			
		||||
    androidTestImplementation(libs.espresso.core)
 | 
			
		||||
    annotationProcessor(libs.room.compiler)
 | 
			
		||||
    implementation("com.github.chrisbanes:PhotoView:2.3.0")
 | 
			
		||||
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
 | 
			
		||||
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
 | 
			
		||||
    implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
          xmlns:tools="http://schemas.android.com/tools">
 | 
			
		||||
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET" />
 | 
			
		||||
    <application
 | 
			
		||||
            android:allowBackup="true"
 | 
			
		||||
            android:dataExtractionRules="@xml/data_extraction_rules"
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
package com.stormtales.notevault;
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.MenuItem;
 | 
			
		||||
import android.view.Menu;
 | 
			
		||||
import com.google.android.material.snackbar.Snackbar;
 | 
			
		||||
import com.google.android.material.navigation.NavigationView;
 | 
			
		||||
import androidx.navigation.NavController;
 | 
			
		||||
import androidx.navigation.Navigation;
 | 
			
		||||
@ -12,6 +11,7 @@ import androidx.navigation.ui.NavigationUI;
 | 
			
		||||
import androidx.drawerlayout.widget.DrawerLayout;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import com.stormtales.notevault.databinding.ActivityMainBinding;
 | 
			
		||||
import com.stormtales.notevault.network.auth.AuthService;
 | 
			
		||||
 | 
			
		||||
public class MainActivity extends AppCompatActivity {
 | 
			
		||||
 | 
			
		||||
@ -26,14 +26,17 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
        setContentView(binding.getRoot());
 | 
			
		||||
 | 
			
		||||
        setSupportActionBar(binding.appBarMain.toolbar);
 | 
			
		||||
        /*binding.appBarMain.fab.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onClick(View view) {
 | 
			
		||||
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
 | 
			
		||||
                        .setAction("Action", null)
 | 
			
		||||
                        .setAnchorView(R.id.fab).show();
 | 
			
		||||
        binding.appBarMain.toolbar.setOnMenuItemClickListener(item -> {
 | 
			
		||||
            if (item.getItemId() == R.id.auth_action) {
 | 
			
		||||
                if (new AuthService(getApplicationContext()).isLoggedIn()) {
 | 
			
		||||
                    //performLogout(); // Logout-Logik aufrufen
 | 
			
		||||
                } else {
 | 
			
		||||
                    showLoginDialog(); // Zeige das Login-Fenster an
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        });*/
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
        DrawerLayout drawer = binding.drawerLayout;
 | 
			
		||||
        NavigationView navigationView = binding.navView;
 | 
			
		||||
        // Passing each menu ID as a set of Ids because each
 | 
			
		||||
@ -60,4 +63,20 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
 | 
			
		||||
                || super.onSupportNavigateUp();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onPrepareOptionsMenu(Menu menu) {
 | 
			
		||||
        MenuItem loginItem = menu.findItem(R.id.auth_action);
 | 
			
		||||
        if (new AuthService(this).isLoggedIn()) {
 | 
			
		||||
            loginItem.setIcon(R.drawable.logout); // Setze das Logout-Symbol
 | 
			
		||||
        } else {
 | 
			
		||||
            loginItem.setIcon(R.drawable.login); // Setze das Login-Symbol
 | 
			
		||||
        }
 | 
			
		||||
        return super.onPrepareOptionsMenu(menu);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void showLoginDialog() {
 | 
			
		||||
        /*LoginFragment loginFragment = new LoginFragment();
 | 
			
		||||
        loginFragment.show(getSupportFragmentManager(), "login");*/
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
package com.stormtales.notevault.data.model;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Data class that captures user information for logged in users retrieved from LoginRepository
 | 
			
		||||
 */
 | 
			
		||||
public class LoggedInUser {
 | 
			
		||||
 | 
			
		||||
    private String userId;
 | 
			
		||||
    private String displayName;
 | 
			
		||||
 | 
			
		||||
    public LoggedInUser(String userId, String displayName) {
 | 
			
		||||
        this.userId = userId;
 | 
			
		||||
        this.displayName = displayName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getUserId() {
 | 
			
		||||
        return userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getDisplayName() {
 | 
			
		||||
        return displayName;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,6 @@
 | 
			
		||||
package com.stormtales.notevault.network;
 | 
			
		||||
 | 
			
		||||
public interface APICallback {
 | 
			
		||||
    void onSuccess();
 | 
			
		||||
    void onError(String error);
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
package com.stormtales.notevault.network;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import com.stormtales.notevault.network.auth.AuthInterceptor;
 | 
			
		||||
import com.stormtales.notevault.network.auth.TokenManager;
 | 
			
		||||
import okhttp3.OkHttpClient;
 | 
			
		||||
import okhttp3.logging.HttpLoggingInterceptor;
 | 
			
		||||
import retrofit2.Retrofit;
 | 
			
		||||
import retrofit2.converter.gson.GsonConverterFactory;
 | 
			
		||||
 | 
			
		||||
public class NetworkModule {
 | 
			
		||||
    private static final String BASE_URL = "https://192.168.178.30:8000/";
 | 
			
		||||
    private static Retrofit retrofit;
 | 
			
		||||
 | 
			
		||||
    public static Retrofit getRetrofitInstance(Context context) {
 | 
			
		||||
        if (retrofit == null) {
 | 
			
		||||
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
 | 
			
		||||
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
 | 
			
		||||
 | 
			
		||||
            TokenManager tokenManager = new TokenManager(context);
 | 
			
		||||
            OkHttpClient client = new OkHttpClient.Builder()
 | 
			
		||||
                    .addInterceptor(new AuthInterceptor(tokenManager))
 | 
			
		||||
                    .addInterceptor(loggingInterceptor)
 | 
			
		||||
                    .build();
 | 
			
		||||
 | 
			
		||||
            retrofit = new Retrofit.Builder()
 | 
			
		||||
                    .baseUrl("http://192.168.178.30:8000/")
 | 
			
		||||
                    .client(client)
 | 
			
		||||
                    .addConverterFactory(GsonConverterFactory.create())
 | 
			
		||||
                    .build();
 | 
			
		||||
        }
 | 
			
		||||
        return retrofit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,16 @@
 | 
			
		||||
package com.stormtales.notevault.network.auth;
 | 
			
		||||
 | 
			
		||||
import retrofit2.Call;
 | 
			
		||||
import retrofit2.http.Body;
 | 
			
		||||
import retrofit2.http.Headers;
 | 
			
		||||
import retrofit2.http.POST;
 | 
			
		||||
 | 
			
		||||
public interface AuthAPI {
 | 
			
		||||
 | 
			
		||||
    @POST("/login/")
 | 
			
		||||
    Call<LoginResponse> login(@Body LoginRequest loginRequest);
 | 
			
		||||
 | 
			
		||||
    /*@POST("/register/")
 | 
			
		||||
    @Headers("Content-Type: application/json")
 | 
			
		||||
    Call<StatusResponse> registration(@Body RegisterRequest registerRequest);*/
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
package com.stormtales.notevault.network.auth;
 | 
			
		||||
 | 
			
		||||
import okhttp3.Interceptor;
 | 
			
		||||
import okhttp3.Request;
 | 
			
		||||
import okhttp3.Response;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public class AuthInterceptor implements Interceptor {
 | 
			
		||||
    private TokenManager tokenManager;
 | 
			
		||||
 | 
			
		||||
    public AuthInterceptor(TokenManager tokenManager) {
 | 
			
		||||
        this.tokenManager = tokenManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Response intercept(Chain chain) throws IOException {
 | 
			
		||||
        Request originalRequest = chain.request();
 | 
			
		||||
 | 
			
		||||
        String token = tokenManager.getToken();
 | 
			
		||||
        if (token == null) {
 | 
			
		||||
            return chain.proceed(originalRequest);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Request authenticatedRequest = originalRequest.newBuilder()
 | 
			
		||||
                .header("Authorization", "Bearer " + token).build();
 | 
			
		||||
        return chain.proceed(authenticatedRequest);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,81 @@
 | 
			
		||||
package com.stormtales.notevault.network.auth;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
import com.stormtales.notevault.network.APICallback;
 | 
			
		||||
import com.stormtales.notevault.network.NetworkModule;
 | 
			
		||||
import retrofit2.Call;
 | 
			
		||||
import retrofit2.Callback;
 | 
			
		||||
import retrofit2.Response;
 | 
			
		||||
 | 
			
		||||
public class AuthService {
 | 
			
		||||
 | 
			
		||||
    private final AuthAPI authAPI;
 | 
			
		||||
    private final TokenManager tokenManager;
 | 
			
		||||
 | 
			
		||||
    public AuthService(Context context) {
 | 
			
		||||
        this.authAPI = NetworkModule.getRetrofitInstance(context).create(AuthAPI.class);
 | 
			
		||||
        this.tokenManager = new TokenManager(context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void performLogin(String email, String password, APICallback callback) {
 | 
			
		||||
        LoginRequest loginRequest = new LoginRequest(email, password);
 | 
			
		||||
 | 
			
		||||
        authAPI.login(loginRequest).enqueue(new Callback<LoginResponse>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
 | 
			
		||||
                if (response.isSuccessful() && response.body() != null) {
 | 
			
		||||
                    String token = response.body().getToken();
 | 
			
		||||
                    saveToken(token);
 | 
			
		||||
                    // Erfolgsrückmeldung an den Callback senden
 | 
			
		||||
                    callback.onSuccess();
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Fehlermeldung an den Callback senden
 | 
			
		||||
                    callback.onError("Login fehlgeschlagen. Überprüfe Benutzername und Passwort.");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onFailure(Call<LoginResponse> call, Throwable t) {
 | 
			
		||||
                // Netzwerkfehler an den Callback senden
 | 
			
		||||
                callback.onError("Netzwerkfehler: " + t.getMessage());
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void performRegistration(String email, String username, String password, APICallback callback) {
 | 
			
		||||
        /*RegisterRequest registerRequest = new RegisterRequest(username, password, email);
 | 
			
		||||
        authService.registration(registerRequest).enqueue(new Callback<StatusResponse>() {
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
 | 
			
		||||
                if(response.isSuccessful() && response.body() != null) {
 | 
			
		||||
                    callback.onSuccess();
 | 
			
		||||
                } else {
 | 
			
		||||
                    callback.onError("Registration fehlgeschlagen. Überprüfe Benutzername und Passwort.");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onFailure(Call<StatusResponse> call, Throwable throwable) {
 | 
			
		||||
                callback.onError("Netzwerkfehler: " + throwable.getMessage());
 | 
			
		||||
            }
 | 
			
		||||
        });*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void saveToken(String token) {
 | 
			
		||||
        tokenManager.saveToken(token);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getToken() {
 | 
			
		||||
        return tokenManager.getToken();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void logout() {
 | 
			
		||||
        tokenManager.clearToken();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isLoggedIn() {
 | 
			
		||||
        return !TextUtils.isEmpty(tokenManager.getToken());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
package com.stormtales.notevault.network.auth;
 | 
			
		||||
 | 
			
		||||
public class LoginRequest {
 | 
			
		||||
    private String email;
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
    public LoginRequest(String email, String password) {
 | 
			
		||||
        this.email = email;
 | 
			
		||||
        this.password = password;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
package com.stormtales.notevault.network.auth;
 | 
			
		||||
 | 
			
		||||
public class LoginResponse {
 | 
			
		||||
    private String token;
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    public String getToken() {
 | 
			
		||||
        return token;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setToken(String token) {
 | 
			
		||||
        this.token = token;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getUsername() {
 | 
			
		||||
        return username;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setUsername(String username) {
 | 
			
		||||
        this.username = username;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
package com.stormtales.notevault.network.auth;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
 | 
			
		||||
public class TokenManager {
 | 
			
		||||
    private static final String PREF_NAME = "app_preferences";
 | 
			
		||||
    private static final String KEY_TOKEN = "jwt_token";
 | 
			
		||||
 | 
			
		||||
    private SharedPreferences sharedPreferences;
 | 
			
		||||
 | 
			
		||||
    public TokenManager(Context context) {
 | 
			
		||||
        sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void saveToken(String token) {
 | 
			
		||||
        SharedPreferences.Editor editor = sharedPreferences.edit();
 | 
			
		||||
        editor.putString(KEY_TOKEN, token);
 | 
			
		||||
        editor.apply();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getToken() {
 | 
			
		||||
        return sharedPreferences.getString(KEY_TOKEN, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void clearToken() {
 | 
			
		||||
        SharedPreferences.Editor editor = sharedPreferences.edit();
 | 
			
		||||
        editor.remove(KEY_TOKEN);
 | 
			
		||||
        editor.apply();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								app/src/main/res/drawable/login.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/drawable/login.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:width="24dp"
 | 
			
		||||
    android:height="24dp"
 | 
			
		||||
    android:viewportWidth="960"
 | 
			
		||||
    android:viewportHeight="960">
 | 
			
		||||
  <path
 | 
			
		||||
      android:pathData="M480,840v-80h280v-560L480,200v-80h280q33,0 56.5,23.5T840,200v560q0,33 -23.5,56.5T760,840L480,840ZM400,680 L345,622 447,520L120,520v-80h327L345,338l55,-58 200,200 -200,200Z"
 | 
			
		||||
      android:fillColor="#e8eaed"/>
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										9
									
								
								app/src/main/res/drawable/logout.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/drawable/logout.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:width="24dp"
 | 
			
		||||
    android:height="24dp"
 | 
			
		||||
    android:viewportWidth="960"
 | 
			
		||||
    android:viewportHeight="960">
 | 
			
		||||
  <path
 | 
			
		||||
      android:pathData="M200,840q-33,0 -56.5,-23.5T120,760v-560q0,-33 23.5,-56.5T200,120h280v80L200,200v560h280v80L200,840ZM640,680 L585,622 687,520L360,520v-80h327L585,338l55,-58 200,200 -200,200Z"
 | 
			
		||||
      android:fillColor="#e8eaed"/>
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										79
									
								
								app/src/main/res/layout/fragment_login.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								app/src/main/res/layout/fragment_login.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
			
		||||
<?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/container"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:paddingBottom="@dimen/fragment_vertical_margin"
 | 
			
		||||
        android:paddingLeft="@dimen/fragment_horizontal_margin"
 | 
			
		||||
        android:paddingRight="@dimen/fragment_horizontal_margin"
 | 
			
		||||
        android:paddingTop="@dimen/fragment_vertical_margin"
 | 
			
		||||
        tools:context=".ui.login.LoginFragment">
 | 
			
		||||
 | 
			
		||||
    <EditText
 | 
			
		||||
            android:id="@+id/username"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="24dp"
 | 
			
		||||
            android:layout_marginTop="96dp"
 | 
			
		||||
            android:layout_marginEnd="24dp"
 | 
			
		||||
            android:autofillHints="@string/prompt_email"
 | 
			
		||||
            android:hint="@string/prompt_email"
 | 
			
		||||
            android:inputType="textEmailAddress"
 | 
			
		||||
            android:selectAllOnFocus="true"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="parent"/>
 | 
			
		||||
 | 
			
		||||
    <EditText
 | 
			
		||||
            android:id="@+id/password"
 | 
			
		||||
            android:layout_width="0dp"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginStart="24dp"
 | 
			
		||||
            android:layout_marginTop="8dp"
 | 
			
		||||
            android:layout_marginEnd="24dp"
 | 
			
		||||
            android:autofillHints="@string/prompt_password"
 | 
			
		||||
            android:hint="@string/prompt_password"
 | 
			
		||||
            android:imeActionLabel="@string/action_sign_in_short"
 | 
			
		||||
            android:imeOptions="actionDone"
 | 
			
		||||
            android:inputType="textPassword"
 | 
			
		||||
            android:selectAllOnFocus="true"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@+id/username"/>
 | 
			
		||||
 | 
			
		||||
    <Button
 | 
			
		||||
            android:id="@+id/login"
 | 
			
		||||
            android:enabled="false"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_gravity="start"
 | 
			
		||||
            android:layout_marginStart="48dp"
 | 
			
		||||
            android:layout_marginTop="16dp"
 | 
			
		||||
            android:layout_marginEnd="48dp"
 | 
			
		||||
            android:layout_marginBottom="64dp"
 | 
			
		||||
            android:text="@string/action_sign_in"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@+id/password"
 | 
			
		||||
            app:layout_constraintVertical_bias="0.2"/>
 | 
			
		||||
 | 
			
		||||
    <ProgressBar
 | 
			
		||||
            android:id="@+id/loading"
 | 
			
		||||
            android:visibility="gone"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_gravity="center"
 | 
			
		||||
            android:layout_marginStart="32dp"
 | 
			
		||||
            android:layout_marginTop="64dp"
 | 
			
		||||
            android:layout_marginEnd="32dp"
 | 
			
		||||
            android:layout_marginBottom="64dp"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="@+id/password"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="@+id/password"
 | 
			
		||||
            app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
            app:layout_constraintVertical_bias="0.3"/>
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
      xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <item android:id="@+id/action_settings"
 | 
			
		||||
          android:title="@string/action_settings"
 | 
			
		||||
          android:orderInCategory="100"
 | 
			
		||||
          app:showAsAction="never"/>
 | 
			
		||||
    <item android:id="@+id/auth_action"
 | 
			
		||||
          android:title="@string/login"
 | 
			
		||||
          android:icon="@drawable/login"
 | 
			
		||||
          app:showAsAction="always"/>
 | 
			
		||||
</menu>
 | 
			
		||||
@ -5,4 +5,7 @@
 | 
			
		||||
    <dimen name="nav_header_vertical_spacing">8dp</dimen>
 | 
			
		||||
    <dimen name="nav_header_height">176dp</dimen>
 | 
			
		||||
    <dimen name="fab_margin">16dp</dimen>
 | 
			
		||||
    <!-- Default screen margins, per the Android Design guidelines. -->
 | 
			
		||||
    <dimen name="fragment_horizontal_margin">16dp</dimen>
 | 
			
		||||
    <dimen name="fragment_vertical_margin">16dp</dimen>
 | 
			
		||||
</resources>
 | 
			
		||||
@ -12,4 +12,14 @@
 | 
			
		||||
    <string name="menu_slideshow">Slideshow</string>
 | 
			
		||||
    <!-- TODO: Remove or change this placeholder text -->
 | 
			
		||||
    <string name="hello_blank_fragment">Hello blank fragment</string>
 | 
			
		||||
    <string name="login">Login</string>
 | 
			
		||||
    <!-- Strings related to login -->
 | 
			
		||||
    <string name="prompt_email">Email</string>
 | 
			
		||||
    <string name="prompt_password">Password</string>
 | 
			
		||||
    <string name="action_sign_in">Sign in or register</string>
 | 
			
		||||
    <string name="action_sign_in_short">Sign in</string>
 | 
			
		||||
    <string name="welcome">"Welcome!"</string>
 | 
			
		||||
    <string name="invalid_username">Not a valid username</string>
 | 
			
		||||
    <string name="invalid_password">Password must be >5 characters</string>
 | 
			
		||||
    <string name="login_failed">"Login failed"</string>
 | 
			
		||||
</resources>
 | 
			
		||||
@ -12,6 +12,7 @@ navigationFragment = "2.8.5"
 | 
			
		||||
navigationUi = "2.8.5"
 | 
			
		||||
roomRuntime = "2.6.1"
 | 
			
		||||
roomCompiler = "2.6.1"
 | 
			
		||||
annotation = "1.9.1"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
 | 
			
		||||
@ -26,6 +27,7 @@ navigation-fragment = { group = "androidx.navigation", name = "navigation-fragme
 | 
			
		||||
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
 | 
			
		||||
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "roomRuntime" }
 | 
			
		||||
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "roomCompiler" }
 | 
			
		||||
annotation = { group = "androidx.annotation", name = "annotation", version.ref = "annotation" }
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
android-application = { id = "com.android.application", version.ref = "agp" }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user