diff --git a/android/.idea/assetWizardSettings.xml b/android/.idea/assetWizardSettings.xml index 2eb36a1..5aa074b 100644 --- a/android/.idea/assetWizardSettings.xml +++ b/android/.idea/assetWizardSettings.xml @@ -14,8 +14,8 @@ diff --git a/android/app/build.gradle b/android/app/build.gradle index eafab24..026882d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,6 +15,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + targetCompatibility 1.8 + sourceCompatibility 1.8 + } } dependencies { @@ -29,6 +33,9 @@ dependencies { implementation 'com.google.firebase:firebase-core:16.0.3' implementation 'com.google.firebase:firebase-messaging:17.3.2' implementation 'com.android.support:support-v4:27.1.1' + + implementation 'com.squareup.okhttp3:okhttp:3.10.0' + implementation 'com.github.kenglxn.QRGen:android:2.5.0' } apply plugin: 'com.google.gms.google-services' diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java index 102f8eb..2f2c607 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java @@ -4,7 +4,9 @@ import android.app.Application; import android.content.Context; import android.widget.Toast; +import com.blackforestbytes.simplecloudnotifier.view.AccountFragment; import com.blackforestbytes.simplecloudnotifier.view.MainActivity; +import com.blackforestbytes.simplecloudnotifier.view.TabAdapter; import java.lang.ref.WeakReference; @@ -28,11 +30,7 @@ public class SCNApp extends Application final MainActivity a = mainActivity.get(); if (a != null) { - a.runOnUiThread(new Runnable() { - public void run() { - Toast.makeText(a, msg, duration).show(); - } - }); + a.runOnUiThread(() -> Toast.makeText(a, msg, duration).show()); } } @@ -43,6 +41,23 @@ public class SCNApp extends Application return false; } + public static void refreshAccountTab() + { + runOnUiThread(() -> + { + MainActivity a = mainActivity.get(); + if (a == null) return; + + TabAdapter ta = a.adpTabs; + if (ta == null) return; + + AccountFragment tf = ta.tab2; + if (tf == null) return; + + tf.updateUI(); + }); + } + public static void register(MainActivity a) { mainActivity = new WeakReference<>(a); diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/CMessageList.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/CMessageList.java index 693a86a..f8a9ff1 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/CMessageList.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/CMessageList.java @@ -65,7 +65,7 @@ public class CMessageList { MessageAdapter a = ref.get(); if (a == null) continue; - a.notifyItemInserted(count); + a.customNotifyItemInserted(count); } CleanUpListener(); } diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/SCNSettings.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/SCNSettings.java new file mode 100644 index 0000000..931a81d --- /dev/null +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/SCNSettings.java @@ -0,0 +1,126 @@ +package com.blackforestbytes.simplecloudnotifier.model; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import android.view.View; + +import com.blackforestbytes.simplecloudnotifier.SCNApp; +import com.google.firebase.iid.FirebaseInstanceId; + +public class SCNSettings +{ + private final static Object _lock = new Object(); + private static SCNSettings _inst = null; + public static SCNSettings inst() + { + synchronized (_lock) + { + if (_inst != null) return _inst; + return _inst = new SCNSettings(); + } + } + + public int quota_curr; + public int quota_max; + public int user_id; + public String user_key; + + public String fcm_token_local; + public String fcm_token_server; + + public SCNSettings() + { + SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE); + + quota_curr = sharedPref.getInt("quota_curr", 0); + quota_max = sharedPref.getInt("quota_max", 0); + user_id = sharedPref.getInt("user_id", -1); + user_key = sharedPref.getString("user_key", ""); + fcm_token_local = sharedPref.getString("fcm_token_local", ""); + fcm_token_server = sharedPref.getString("fcm_token_server", ""); + } + + public void save() + { + SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE); + SharedPreferences.Editor e = sharedPref.edit(); + + e.putInt("quota_curr", quota_curr); + e.putInt("quota_max", quota_max); + e.putInt("user_id", user_id); + e.putString("user_key", user_key); + e.putString("fcm_token_local", fcm_token_local); + e.putString("fcm_token_server", fcm_token_server); + + e.apply(); + } + + public boolean isConnected() + { + return user_id>=0 && user_key != null && !user_key.isEmpty(); + } + + public String createOnlineURL() + { + if (!isConnected()) return ServerCommunication.BASE_URL + "index.php"; + return ServerCommunication.BASE_URL + "index.php?preset_user_id="+user_id+"&preset_user_key="+user_key; + } + + public void setServerToken(String token, View loader) + { + if (isConnected()) + { + fcm_token_local = token; + save(); + if (!fcm_token_local.equals(fcm_token_server)) ServerCommunication.update(user_id, user_key, fcm_token_local, loader); + } + else + { + fcm_token_local = token; + save(); + ServerCommunication.register(fcm_token_local, loader); + } + } + + public void work(Activity a) + { + FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(a, instanceIdResult -> + { + String newToken = instanceIdResult.getToken(); + Log.e("FB::GetInstanceId", newToken); + SCNSettings.inst().setServerToken(newToken, null); + }).addOnCompleteListener(r -> + { + if (isConnected()) ServerCommunication.info(user_id, user_key, null); + }); + } + + public void reset(View loader) + { + if (!isConnected()) return; + + ServerCommunication.update(user_id, user_key, loader); + } + + public void refresh(View loader, Activity a) + { + if (isConnected()) + { + ServerCommunication.info(user_id, user_key, loader); + } + else + { + FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(a, instanceIdResult -> + { + String newToken = instanceIdResult.getToken(); + Log.e("FB::GetInstanceId", newToken); + SCNSettings.inst().setServerToken(newToken, loader); + }).addOnCompleteListener(r -> + { + if (isConnected()) ServerCommunication.info(user_id, user_key, null); + }); + } + } +} diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java new file mode 100644 index 0000000..5b691b1 --- /dev/null +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java @@ -0,0 +1,276 @@ +package com.blackforestbytes.simplecloudnotifier.model; + +import android.os.Build; +import android.util.Log; +import android.view.View; + +import com.blackforestbytes.simplecloudnotifier.BuildConfig; +import com.blackforestbytes.simplecloudnotifier.SCNApp; + +import org.json.JSONObject; +import org.json.JSONTokener; + +import java.io.IOException; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class ServerCommunication +{ + //public static final String BASE_URL = "https://simplecloudnotifier.blackforestbytes.com/"; + public static final String BASE_URL = "http://10.0.2.2:1010/"; + + private static final OkHttpClient client = new OkHttpClient(); + + private ServerCommunication(){ throw new Error("no."); } + + public static void register(String token, View loader) + { + try + { + Request request = new Request.Builder() + .url(BASE_URL + "register.php?fcm_token="+token) + .build(); + + client.newCall(request).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); }); + } + + @Override + public void onResponse(Call call, Response response) + { + try (ResponseBody responseBody = response.body()) + { + if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); + if (responseBody == null) throw new IOException("No response"); + + String r = responseBody.string(); + Log.d("Server::Response", r); + + JSONObject json = (JSONObject) new JSONTokener(r).nextValue(); + + if (!json.getBoolean("success")) + { + SCNApp.showToast(json.getString("message"), 4000); + return; + } + + SCNSettings.inst().user_id = json.getInt("user_id"); + SCNSettings.inst().user_key = json.getString("user_key"); + SCNSettings.inst().fcm_token_server = token; + SCNSettings.inst().quota_curr = json.getInt("quota"); + SCNSettings.inst().quota_max = json.getInt("quota_max"); + SCNSettings.inst().save(); + + SCNApp.refreshAccountTab(); + } + catch (Exception e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + finally + { + SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); }); + } + } + }); + } + catch (Exception e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + } + + public static void update(int id, String key, String token, View loader) + { + try + { + Request request = new Request.Builder() + .url(BASE_URL + "update.php?user_id="+id+"&user_key="+key+"&fcm_token="+token) + .build(); + + client.newCall(request).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); }); + } + + @Override + public void onResponse(Call call, Response response) + { + try (ResponseBody responseBody = response.body()) + { + if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); + if (responseBody == null) throw new IOException("No response"); + + String r = responseBody.string(); + Log.d("Server::Response", r); + + JSONObject json = (JSONObject) new JSONTokener(r).nextValue(); + + if (!json.getBoolean("success")) + { + SCNApp.showToast(json.getString("message"), 4000); + return; + } + + SCNSettings.inst().user_id = json.getInt("user_id"); + SCNSettings.inst().user_key = json.getString("user_key"); + SCNSettings.inst().fcm_token_server = token; + SCNSettings.inst().quota_curr = json.getInt("quota"); + SCNSettings.inst().quota_max = json.getInt("quota_max"); + SCNSettings.inst().save(); + + SCNApp.refreshAccountTab(); + } + catch (Exception e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + finally + { + SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); }); + } + } + }); + } + catch (Exception e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + } + + public static void update(int id, String key, View loader) + { + try + { + Request request = new Request.Builder() + .url(BASE_URL + "update.php?user_id=" + id + "&user_key=" + key) + .build(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + + @Override + public void onResponse(Call call, Response response) { + try (ResponseBody responseBody = response.body()) { + if (!response.isSuccessful()) + throw new IOException("Unexpected code " + response); + if (responseBody == null) throw new IOException("No response"); + + String r = responseBody.string(); + Log.d("Server::Response", r); + + JSONObject json = (JSONObject) new JSONTokener(r).nextValue(); + + if (!json.getBoolean("success")) { + SCNApp.showToast(json.getString("message"), 4000); + return; + } + + SCNSettings.inst().user_id = json.getInt("user_id"); + SCNSettings.inst().user_key = json.getString("user_key"); + SCNSettings.inst().quota_curr = json.getInt("quota"); + SCNSettings.inst().quota_max = json.getInt("quota_max"); + SCNSettings.inst().save(); + + SCNApp.refreshAccountTab(); + } catch (Exception e) { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } finally { + SCNApp.runOnUiThread(() -> { + if (loader != null) loader.setVisibility(View.GONE); + }); + } + } + }); + } + catch (Exception e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + } + + public static void info(int id, String key, View loader) + { + try + { + Request request = new Request.Builder() + .url(BASE_URL + "info.php?user_id=" + id + "&user_key=" + key) + .build(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + SCNApp.runOnUiThread(() -> { + if (loader != null) loader.setVisibility(View.GONE); + }); + } + + @Override + public void onResponse(Call call, Response response) { + try (ResponseBody responseBody = response.body()) { + if (!response.isSuccessful()) + throw new IOException("Unexpected code " + response); + if (responseBody == null) throw new IOException("No response"); + + String r = responseBody.string(); + Log.d("Server::Response", r); + + JSONObject json = (JSONObject) new JSONTokener(r).nextValue(); + + if (!json.getBoolean("success")) { + SCNApp.showToast(json.getString("message"), 4000); + return; + } + + SCNSettings.inst().user_id = json.getInt("user_id"); + SCNSettings.inst().quota_curr = json.getInt("quota"); + SCNSettings.inst().quota_max = json.getInt("quota_max"); + SCNSettings.inst().save(); + + SCNApp.refreshAccountTab(); + } catch (Exception e) { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } finally { + SCNApp.runOnUiThread(() -> { + if (loader != null) loader.setVisibility(View.GONE); + }); + } + } + }); + } + catch (Exception e) + { + e.printStackTrace(); + SCNApp.showToast("Communication with server failed", 4000); + } + } +} diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/FBMService.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/FBMService.java index 2a78c79..79873dc 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/FBMService.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/FBMService.java @@ -5,6 +5,7 @@ import android.widget.Toast; import com.blackforestbytes.simplecloudnotifier.SCNApp; import com.blackforestbytes.simplecloudnotifier.model.CMessageList; +import com.blackforestbytes.simplecloudnotifier.model.SCNSettings; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; @@ -14,6 +15,7 @@ public class FBMService extends FirebaseMessagingService public void onNewToken(String token) { Log.i("Firebase::NewToken", token); + SCNSettings.inst().setServerToken(token, null); } @Override diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/AccountFragment.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/AccountFragment.java index 4051949..eeb2418 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/AccountFragment.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/AccountFragment.java @@ -1,13 +1,33 @@ package com.blackforestbytes.simplecloudnotifier.view; +import android.annotation.SuppressLint; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.VectorDrawable; +import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; +import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; import com.blackforestbytes.simplecloudnotifier.R; +import com.blackforestbytes.simplecloudnotifier.SCNApp; +import com.blackforestbytes.simplecloudnotifier.model.CMessageList; +import com.blackforestbytes.simplecloudnotifier.model.SCNSettings; +import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication; + +import net.glxn.qrgen.android.QRCode; +import net.glxn.qrgen.core.image.ImageType; + +import static android.content.Context.CLIPBOARD_SERVICE; public class AccountFragment extends Fragment { @@ -19,7 +39,82 @@ public class AccountFragment extends Fragment @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_account, container, false); + View v = inflater.inflate(R.layout.fragment_account, container, false); + + updateUI(v); + + v.findViewById(R.id.btnCopyUserID).setOnClickListener(cv -> + { + ClipboardManager clipboard = (ClipboardManager) cv.getContext().getSystemService(CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText("UserID", String.valueOf(SCNSettings.inst().user_id))); + SCNApp.showToast("Copied userID to clipboard", 1000); + }); + + v.findViewById(R.id.btnCopyUserKey).setOnClickListener(cv -> + { + ClipboardManager clipboard = (ClipboardManager) cv.getContext().getSystemService(CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText("UserKey", String.valueOf(SCNSettings.inst().user_key))); + SCNApp.showToast("Copied key to clipboard", 1000); + }); + + v.findViewById(R.id.btnAccountReset).setOnClickListener(cv -> + { + View lpnl = v.findViewById(R.id.loadingPanel); + lpnl.setVisibility(View.VISIBLE); + SCNSettings.inst().reset(lpnl); + }); + + v.findViewById(R.id.btnClearLocalStorage).setOnClickListener(cv -> + { + CMessageList.inst().Messages.clear(); + CMessageList.inst().fullSave(); + SCNApp.showToast("Notifications cleared", 1000); + }); + + v.findViewById(R.id.btnQR).setOnClickListener(cv -> + { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(SCNSettings.inst().createOnlineURL())); + startActivity(browserIntent); + }); + + v.findViewById(R.id.btnRefresh).setOnClickListener(cv -> + { + View lpnl = v.findViewById(R.id.loadingPanel); + lpnl.setVisibility(View.VISIBLE); + SCNSettings.inst().refresh(lpnl, getActivity()); + }); + + return v; } + public void updateUI() + { + updateUI(getView()); + } + + @SuppressLint("DefaultLocale") + public void updateUI(View v) + { + TextView tvUserID = v.findViewById(R.id.tvUserID); + TextView tvUserKey = v.findViewById(R.id.tvUserKey); + TextView tvQuota = v.findViewById(R.id.tvQuota); + ImageButton btnQR = v.findViewById(R.id.btnQR); + + SCNSettings s = SCNSettings.inst(); + + if (s.isConnected()) + { + tvUserID.setText(String.valueOf(s.user_id)); + tvUserKey.setText(s.user_key); + tvQuota.setText(String.format("%d / %d", s.quota_curr, s.quota_max)); + btnQR.setImageBitmap(QRCode.from(s.createOnlineURL()).to(ImageType.PNG).withSize(512, 512).bitmap()); + } + else + { + tvUserID.setText(R.string.str_not_connected); + tvUserKey.setText(R.string.str_not_connected); + tvQuota.setText(R.string.str_not_connected); + btnQR.setImageResource(R.drawable.qr_default); + } + } } diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MainActivity.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MainActivity.java index 50e4eee..33b0d38 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MainActivity.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MainActivity.java @@ -8,34 +8,40 @@ import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import com.blackforestbytes.simplecloudnotifier.R; import com.blackforestbytes.simplecloudnotifier.SCNApp; import com.blackforestbytes.simplecloudnotifier.model.CMessageList; +import com.blackforestbytes.simplecloudnotifier.model.SCNSettings; +import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication; +import com.google.firebase.iid.FirebaseInstanceId; public class MainActivity extends AppCompatActivity { + public TabAdapter adpTabs; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); - TabLayout tabLayout = findViewById(R.id.tab_layout); - tabLayout.addTab(tabLayout.newTab().setText("Notifications")); - tabLayout.addTab(tabLayout.newTab().setText("Account")); - tabLayout.addTab(tabLayout.newTab().setText("Settings")); - tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); - - final ViewPager viewPager = findViewById(R.id.pager); - final PagerAdapter adapter = new TabAdapter(getSupportFragmentManager()); + ViewPager viewPager = findViewById(R.id.pager); + PagerAdapter adapter = adpTabs = new TabAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); - viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); + + TabLayout tabLayout = findViewById(R.id.tab_layout); + tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); + tabLayout.setupWithViewPager(viewPager); SCNApp.register(this); + + SCNSettings.inst().work(this); } @Override diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MessageAdapter.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MessageAdapter.java index 401d3ab..03e850a 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MessageAdapter.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/MessageAdapter.java @@ -15,8 +15,11 @@ import com.blackforestbytes.simplecloudnotifier.model.CMessageList; public class MessageAdapter extends RecyclerView.Adapter { - public MessageAdapter() + private final View vNoElements; + + public MessageAdapter(View noElementsView) { + vNoElements = noElementsView; CMessageList.inst().register(this); } @@ -42,6 +45,18 @@ public class MessageAdapter extends RecyclerView.Adapter return CMessageList.inst().size(); } + public void customNotifyItemInserted(int idx) + { + notifyItemInserted(idx); + vNoElements.setVisibility(getItemCount()>0 ? View.VISIBLE : View.GONE); + } + + public void customNotifyDataSetChanged() + { + notifyDataSetChanged(); + vNoElements.setVisibility(getItemCount()>0 ? View.VISIBLE : View.GONE); + } + private class MessagePresenter extends RecyclerView.ViewHolder implements View.OnClickListener { private TextView tvTimestamp; diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/NotificationsFragment.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/NotificationsFragment.java index 70eb627..6824958 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/NotificationsFragment.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/NotificationsFragment.java @@ -27,7 +27,7 @@ public class NotificationsFragment extends Fragment RecyclerView rvMessages = v.findViewById(R.id.rvMessages); rvMessages.setLayoutManager(new LinearLayoutManager(this.getContext(), RecyclerView.VERTICAL, true)); - rvMessages.setAdapter(new MessageAdapter()); + rvMessages.setAdapter(new MessageAdapter(v.findViewById(R.id.tvNoElements))); return v; } diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/TabAdapter.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/TabAdapter.java index 6d69993..f0d851f 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/TabAdapter.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/TabAdapter.java @@ -6,6 +6,10 @@ import android.support.v4.app.FragmentStatePagerAdapter; public class TabAdapter extends FragmentStatePagerAdapter { + public NotificationsFragment tab1 = new NotificationsFragment(); + public AccountFragment tab2 = new AccountFragment(); + public SettingsFragment tab3 = new SettingsFragment(); + public TabAdapter(FragmentManager fm) { super(fm); @@ -16,16 +20,28 @@ public class TabAdapter extends FragmentStatePagerAdapter { switch (position) { case 0: - return new NotificationsFragment(); + return tab1; case 1: - return new AccountFragment(); + return tab2; case 2: - return new SettingsFragment(); + return tab3; default: return null; } } + @Override + public CharSequence getPageTitle(int position) + { + switch (position) + { + case 0: return "Notifications"; + case 1: return "Account"; + case 2: return "Settings"; + default: return null; + } + } + @Override public int getCount() { return 3; diff --git a/android/app/src/main/res/drawable/ic_refresh.xml b/android/app/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 0000000..45dc20c --- /dev/null +++ b/android/app/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,6 @@ + + + diff --git a/android/app/src/main/res/drawable/qr_default.xml b/android/app/src/main/res/drawable/qr_default.xml index d47e01b..344e92c 100644 --- a/android/app/src/main/res/drawable/qr_default.xml +++ b/android/app/src/main/res/drawable/qr_default.xml @@ -1,5 +1,5 @@ diff --git a/android/app/src/main/res/layout/fragment_account.xml b/android/app/src/main/res/layout/fragment_account.xml index 16fcef8..d6bd560 100644 --- a/android/app/src/main/res/layout/fragment_account.xml +++ b/android/app/src/main/res/layout/fragment_account.xml @@ -1,197 +1,238 @@ - + android:layout_height="match_parent" + tools:context=".view.AccountFragment"> - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +