diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..5f6f784 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/IntroActivity.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/IntroActivity.java index aeb1631..0dcd3bc 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/IntroActivity.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/IntroActivity.java @@ -1,22 +1,13 @@ package com.cringe_studios.cringe_authenticator; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; import android.view.ViewGroup; -import android.widget.VideoView; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.cringe_studios.cringe_authenticator.databinding.ActivityIntroBinding; diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java index b6952b7..12f08c2 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/MainActivity.java @@ -29,7 +29,6 @@ import com.cringe_studios.cringe_authenticator.fragment.SettingsFragment; import com.cringe_studios.cringe_authenticator.scanner.QRScannerActivity; import com.cringe_studios.cringe_authenticator.scanner.QRScannerContract; import com.cringe_studios.cringe_authenticator.util.NavigationUtil; -import com.cringe_studios.cringe_authenticator.util.SettingsUtil; import java.util.concurrent.Executor; @@ -76,8 +75,7 @@ public class MainActivity extends AppCompatActivity { Fragment fragment = NavigationUtil.getCurrentFragment(this); if(fragment instanceof DynamicFragment) { DynamicFragment frag = (DynamicFragment) fragment; - SettingsUtil.addOTP(getSharedPreferences(SettingsUtil.GROUPS_PREFS_NAME, MODE_PRIVATE), frag.getGroupName(), obj); - frag.loadOTPs(); + frag.addOTP(obj); } Log.i("AMOGUS", "Actually got something bruh" + obj); }); @@ -148,10 +146,6 @@ public class MainActivity extends AppCompatActivity { NavigationUtil.navigate(this, SettingsFragment.class, null); } - public void addCode(MenuItem item) { - // TODO: add code - } - public void scanCode(View view) { Log.i("AMOGUS", "Scan"); Intent intent = new Intent(this, QRScannerActivity.class); diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/OTPData.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/OTPData.java index 74e9bb7..7f5f353 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/OTPData.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/OTPData.java @@ -1,10 +1,13 @@ package com.cringe_studios.cringe_authenticator; +import androidx.annotation.NonNull; + import com.cringe_studios.cringe_authenticator_library.OTP; import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm; import com.cringe_studios.cringe_authenticator_library.OTPType; import java.io.Serializable; +import java.util.Objects; public class OTPData implements Serializable { @@ -16,6 +19,9 @@ public class OTPData implements Serializable { private int period; private int counter; + // Cached + private OTP otp; + public OTPData(String name, OTPType type, String secret, OTPAlgorithm algorithm, int digits, int period, int counter) { this.name = name; this.type = type; @@ -56,9 +62,11 @@ public class OTPData implements Serializable { public OTP toOTP() { // TODO: checksum - return OTP.createNewOTP(type, secret, algorithm, digits, counter, period, false); + if(otp != null) return otp; + return otp = OTP.createNewOTP(type, secret, algorithm, digits, counter, period, false); } + @NonNull @Override public String toString() { return "OTPData{" + @@ -71,4 +79,17 @@ public class OTPData implements Serializable { ", counter=" + counter + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OTPData otpData = (OTPData) o; + return digits == otpData.digits && period == otpData.period && counter == otpData.counter && Objects.equals(name, otpData.name) && type == otpData.type && Objects.equals(secret, otpData.secret) && algorithm == otpData.algorithm; + } + + @Override + public int hashCode() { + return Objects.hash(name, type, secret, algorithm, digits, period, counter); + } } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/DynamicFragment.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/DynamicFragment.java index c448680..7923dc4 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/DynamicFragment.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/DynamicFragment.java @@ -5,7 +5,6 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -16,10 +15,10 @@ import androidx.fragment.app.Fragment; import com.cringe_studios.cringe_authenticator.OTPData; import com.cringe_studios.cringe_authenticator.databinding.FragmentDynamicBinding; -import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding; +import com.cringe_studios.cringe_authenticator.otplist.OTPListAdapter; +import com.cringe_studios.cringe_authenticator.otplist.OTPListItem; import com.cringe_studios.cringe_authenticator.util.FabUtil; import com.cringe_studios.cringe_authenticator.util.SettingsUtil; -import com.cringe_studios.cringe_authenticator_library.OTP; import java.util.List; @@ -35,6 +34,8 @@ public class DynamicFragment extends Fragment { private Runnable refreshCodes; + private OTPListAdapter otpListAdapter; + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -47,24 +48,21 @@ public class DynamicFragment extends Fragment { groupName = requireArguments().getString(DynamicFragment.BUNDLE_GROUP); - /*String[] totps = new String[]{"Code 1", "Code 2", groupName}; - for(String totp : totps) { - AuthenticateTotpBinding itemBinding = AuthenticateTotpBinding.inflate(inflater); - itemBinding.displayName.setText(totp); - binding.itemList.addView(itemBinding.getRoot()); - }*/ + FabUtil.showFabs(requireActivity()); + + otpListAdapter = new OTPListAdapter(getContext()); + binding.itemList.setAdapter(otpListAdapter); loadOTPs(); - FabUtil.showFabs(getActivity()); - handler = new Handler(Looper.getMainLooper()); refreshCodes = () -> { for(int i = 0; i < binding.itemList.getChildCount(); i++) { - View v = binding.itemList.getChildAt(i); - OTP otp = (OTP) v.getTag(); - otp.getPin(); + OTPListItem vh = (OTPListItem) binding.itemList.findViewHolderForAdapterPosition(i); + if(vh == null) continue; + vh.getBinding().otpCode.setText(vh.getOTPData().toOTP().getPin()); } + handler.postDelayed(refreshCodes, 1000L); }; @@ -73,21 +71,21 @@ public class DynamicFragment extends Fragment { return binding.getRoot(); } - public void loadOTPs() { - SharedPreferences prefs = getActivity().getSharedPreferences(SettingsUtil.GROUPS_PREFS_NAME, Context.MODE_PRIVATE); + private void loadOTPs() { + SharedPreferences prefs = requireActivity().getSharedPreferences(SettingsUtil.GROUPS_PREFS_NAME, Context.MODE_PRIVATE); List data = SettingsUtil.getOTPs(prefs, groupName); - Log.i("AMOGUS", "OTPS: " + data); - binding.itemList.removeAllViews(); for(OTPData otp : data) { - OtpCodeBinding itemBinding = OtpCodeBinding.inflate(getLayoutInflater()); - itemBinding.label.setText(otp.getName()); - itemBinding.otpCode.setText(otp.toOTP().getPin()); - itemBinding.getRoot().setTag(otp.toOTP()); - binding.itemList.addView(itemBinding.getRoot()); + otpListAdapter.add(otp); } } + public void addOTP(OTPData data) { + SharedPreferences prefs = requireActivity().getSharedPreferences(SettingsUtil.GROUPS_PREFS_NAME, Context.MODE_PRIVATE); + SettingsUtil.addOTP(prefs, groupName, data); + otpListAdapter.add(data); + } + @Override public void onDestroyView() { super.onDestroyView(); @@ -100,8 +98,4 @@ public class DynamicFragment extends Fragment { super.onDestroy(); } - public String getGroupName() { - return groupName; - } - } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/HomeFragment.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/HomeFragment.java index eeb339d..7f1ae15 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/HomeFragment.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/HomeFragment.java @@ -16,9 +16,9 @@ public class HomeFragment extends Fragment { private FragmentHomeBinding binding; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentHomeBinding.inflate(inflater, container, false); - FabUtil.hideFabs(getActivity()); + FabUtil.hideFabs(requireActivity()); return binding.getRoot(); } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java index efb5198..acda8ee 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/MenuFragment.java @@ -4,17 +4,14 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.view.LayoutInflater; -import android.view.Menu; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.cringe_studios.cringe_authenticator.R; import com.cringe_studios.cringe_authenticator.databinding.FragmentMenuBinding; import com.cringe_studios.cringe_authenticator.databinding.MenuItemBinding; import com.cringe_studios.cringe_authenticator.util.FabUtil; @@ -29,7 +26,7 @@ public class MenuFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = FragmentMenuBinding.inflate(inflater); - SharedPreferences pr = getContext().getSharedPreferences("menu", Context.MODE_PRIVATE); + SharedPreferences pr = requireContext().getSharedPreferences("menu", Context.MODE_PRIVATE); String[] items = {"a", "b"}; @@ -42,7 +39,7 @@ public class MenuFragment extends Fragment { NavigationUtil.navigate(this, DynamicFragment.class, bundle); }); itemBinding.button.setOnLongClickListener(view -> { - new AlertDialog.Builder(getContext()) + new AlertDialog.Builder(requireContext()) .setTitle("Delete?") .setMessage("Delete this?") .setPositiveButton("Yes", (dialog, which) -> itemBinding.button.setVisibility(View.GONE)) @@ -59,7 +56,7 @@ public class MenuFragment extends Fragment { // TODO: edit mode }); - FabUtil.hideFabs(getActivity()); + FabUtil.hideFabs(requireActivity()); return binding.getRoot(); } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/SettingsFragment.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/SettingsFragment.java index f0625ba..95f8e9b 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/SettingsFragment.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/fragment/SettingsFragment.java @@ -7,7 +7,6 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.navigation.NavController; import androidx.navigation.Navigation; @@ -30,7 +29,7 @@ public class SettingsFragment extends Fragment { controller.navigate(R.id.FirstFragment); }); - FabUtil.hideFabs(getActivity()); + FabUtil.hideFabs(requireActivity()); return binding.getRoot(); } diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java new file mode 100644 index 0000000..91c0490 --- /dev/null +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListAdapter.java @@ -0,0 +1,56 @@ +package com.cringe_studios.cringe_authenticator.otplist; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.cringe_studios.cringe_authenticator.OTPData; +import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding; + +import java.util.ArrayList; +import java.util.List; + +public class OTPListAdapter extends RecyclerView.Adapter { + + private LayoutInflater inflater; + + private List items; + + public OTPListAdapter(Context context) { + this.inflater = LayoutInflater.from(context); + this.items = new ArrayList<>(); + } + + @NonNull + @Override + public OTPListItem onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + OtpCodeBinding binding = OtpCodeBinding.inflate(inflater, parent, false); + return new OTPListItem(binding); + } + + @Override + public void onBindViewHolder(@NonNull OTPListItem holder, int position) { + holder.setOTPData(items.get(position)); + holder.getBinding().label.setText(holder.getOTPData().getName()); + } + + @Override + public int getItemCount() { + return items.size(); + } + + public void add(OTPData data) { + items.add(data); + notifyItemInserted(items.size() - 1); + } + + public void remove(OTPData data) { + int index = items.indexOf(data); + items.remove(data); + notifyItemRemoved(index); + } + +} diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java new file mode 100644 index 0000000..c40f722 --- /dev/null +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/otplist/OTPListItem.java @@ -0,0 +1,32 @@ +package com.cringe_studios.cringe_authenticator.otplist; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.cringe_studios.cringe_authenticator.OTPData; +import com.cringe_studios.cringe_authenticator.databinding.OtpCodeBinding; + +public class OTPListItem extends RecyclerView.ViewHolder { + + private OtpCodeBinding binding; + + private OTPData otpData; + + public OTPListItem(OtpCodeBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + + public @NonNull OtpCodeBinding getBinding() { + return binding; + } + + public void setOTPData(OTPData otpData) { + this.otpData = otpData; + } + + public OTPData getOTPData() { + return otpData; + } + +} diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/scanner/QRScannerActivity.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/scanner/QRScannerActivity.java index 38f3083..1bddf9c 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/scanner/QRScannerActivity.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/scanner/QRScannerActivity.java @@ -8,7 +8,6 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.util.Log; -import android.util.Size; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -22,14 +21,11 @@ import androidx.camera.core.ImageProxy; import androidx.camera.core.Preview; import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.core.content.ContextCompat; -import androidx.lifecycle.LifecycleOwner; import com.cringe_studios.cringe_authenticator.OTPData; import com.cringe_studios.cringe_authenticator.databinding.ActivityQrScannerBinding; -import com.cringe_studios.cringe_authenticator_library.OTP; import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm; import com.cringe_studios.cringe_authenticator_library.OTPType; -import com.google.android.gms.common.api.CommonStatusCodes; import com.google.common.util.concurrent.ListenableFuture; import com.google.mlkit.vision.barcode.BarcodeScanner; import com.google.mlkit.vision.barcode.BarcodeScannerOptions; @@ -37,8 +33,6 @@ import com.google.mlkit.vision.barcode.BarcodeScanning; import com.google.mlkit.vision.barcode.common.Barcode; import com.google.mlkit.vision.common.InputImage; -import java.net.URI; -import java.net.URL; import java.util.concurrent.ExecutionException; public class QRScannerActivity extends AppCompatActivity { diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/util/NavigationUtil.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/util/NavigationUtil.java index d9d957e..66fd920 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/util/NavigationUtil.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/util/NavigationUtil.java @@ -1,14 +1,12 @@ package com.cringe_studios.cringe_authenticator.util; import android.os.Bundle; -import android.view.View; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import com.cringe_studios.cringe_authenticator.R; -import com.google.android.material.floatingactionbutton.FloatingActionButton; public class NavigationUtil { diff --git a/app/src/main/java/com/cringe_studios/cringe_authenticator/util/SettingsUtil.java b/app/src/main/java/com/cringe_studios/cringe_authenticator/util/SettingsUtil.java index 840a3b2..62df346 100644 --- a/app/src/main/java/com/cringe_studios/cringe_authenticator/util/SettingsUtil.java +++ b/app/src/main/java/com/cringe_studios/cringe_authenticator/util/SettingsUtil.java @@ -29,7 +29,7 @@ public class SettingsUtil { otps.add(data); prefs.edit() - .putString("group." + group, GSON.toJson(otps.toArray(new OTPData[otps.size()]))) + .putString("group." + group, GSON.toJson(otps.toArray(new OTPData[0]))) .apply(); } diff --git a/app/src/main/res/layout/fragment_dynamic.xml b/app/src/main/res/layout/fragment_dynamic.xml index c94ec17..a04d39c 100644 --- a/app/src/main/res/layout/fragment_dynamic.xml +++ b/app/src/main/res/layout/fragment_dynamic.xml @@ -4,20 +4,22 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".fragment.SecondFragment"> + tools:context=".fragment.DynamicFragment"> - + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index c62758a..9b789af 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -19,7 +19,7 @@ android:text="Enable something" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - tools:layout_editor_absoluteY="16dp" /> + app:layout_constraintTop_toTopOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/otp_code.xml b/app/src/main/res/layout/otp_code.xml index a592a06..1541d76 100644 --- a/app/src/main/res/layout/otp_code.xml +++ b/app/src/main/res/layout/otp_code.xml @@ -2,28 +2,23 @@ - + - + android:layout_height="wrap_content" + android:text="My OTP" + android:textAlignment="center" + android:textSize="16sp" /> - - + \ No newline at end of file