sometimes you just have to buy a lobster

This commit is contained in:
pegasko 2024-06-07 02:59:07 +03:00
parent 1792656736
commit 3de1749b0d
46 changed files with 1098 additions and 359 deletions

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" > xmlns:tools="http://schemas.android.com/tools" >
@ -13,7 +29,7 @@
android:theme="@style/Theme.Yeeemp" android:theme="@style/Theme.Yeeemp"
tools:targetApi="31" > tools:targetApi="31" >
<activity <activity
android:name=".ui.activity.MainActivity" android:name=".ui.activity.QueueListActivity"
android:exported="true" android:exported="true"
android:theme="@style/Theme.Yeeemp.Green" > android:theme="@style/Theme.Yeeemp.Green" >
<intent-filter> <intent-filter>
@ -22,6 +38,11 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ui.activity.EventListActivity"
android:exported="true"
android:theme="@style/Theme.Yeeemp.Green" >
</activity>
</application> </application>
</manifest> </manifest>

View file

@ -20,8 +20,8 @@ public interface Event {
int getId(); int getId();
long getTimestamp(); long getTimestamp();
void setTimestamp(long timestamp); void setTimestamp(long timestamp);
String getMessage(); String getComment();
void setMessage(String message); void setComment(String comment);
void addTag(Tag tag); void addTag(Tag tag);
void removeTag(Tag tag); void removeTag(Tag tag);
Tag[] getTags(); Tag[] getTags();

View file

@ -17,5 +17,6 @@
package art.pegasko.yeeemp.base; package art.pegasko.yeeemp.base;
public interface EventMaker { public interface EventMaker {
Event createInQueue(Queue queue); Event create();
void delete(Event event);
} }

View file

@ -21,6 +21,7 @@ public interface Queue {
String getName(); String getName();
void setName(String name); void setName(String name);
Event[] getEvents(); Event[] getEvents();
int getEventCount();
void addEvent(Event event); void addEvent(Event event);
void removeEvent(Event event); void removeEvent(Event event);
Tag[] getGlobalTags(); Tag[] getGlobalTags();

View file

@ -17,6 +17,8 @@
package art.pegasko.yeeemp.base; package art.pegasko.yeeemp.base;
public interface QueueMaker { public interface QueueMaker {
Queue getById(int id);
Queue create(); Queue create();
void delete(Queue queue);
Queue[] list(); Queue[] list();
} }

View file

@ -25,19 +25,16 @@ import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import art.pegasko.yeeemp.base.Event; import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.Tag; import art.pegasko.yeeemp.base.Tag;
public class EventImpl implements Event { public class EventImpl implements Event {
public static final String TAG = EventImpl.class.getSimpleName(); public static final String TAG = EventImpl.class.getSimpleName();
private final SQLiteDatabase db; private final SQLiteDatabase db;
private final Queue queue;
private final int id; private final int id;
protected EventImpl(SQLiteDatabase db, Queue queue, int id) { protected EventImpl(SQLiteDatabase db, int id) {
this.db = db; this.db = db;
this.queue = queue;
this.id = id; this.id = id;
} }
@ -52,8 +49,8 @@ public class EventImpl implements Event {
Cursor cursor = db.query( Cursor cursor = db.query(
"event", "event",
new String[] { "timestamp" }, new String[] { "timestamp" },
"query_id = ? AND id = ?", "id = ?",
new String[] { Integer.toString(queue.getId()), Integer.toString(this.getId()) }, new String[] { Integer.toString(this.getId()) },
null, null,
null, null,
null null
@ -82,11 +79,11 @@ public class EventImpl implements Event {
} }
@Override @Override
public String getMessage() { public String getComment() {
synchronized (this.db) { synchronized (this.db) {
Cursor cursor = db.query( Cursor cursor = db.query(
"event", "event",
new String[] { "message" }, new String[] { "comment" },
"id = ?", "id = ?",
new String[] { Integer.toString(this.getId()) }, new String[] { Integer.toString(this.getId()) },
null, null,
@ -103,10 +100,10 @@ public class EventImpl implements Event {
} }
@Override @Override
public void setMessage(String message) { public void setComment(String comment) {
synchronized (this.db) { synchronized (this.db) {
ContentValues cv = new ContentValues(); ContentValues cv = new ContentValues();
cv.put("message", message); cv.put("comment", comment);
db.update( db.update(
"event", "event",
cv, cv,
@ -148,7 +145,7 @@ public class EventImpl implements Event {
cv.put("tag_id", tag.getId()); cv.put("tag_id", tag.getId());
db.insertOrThrow("event_tag", null, cv); db.insertOrThrow("event_tag", null, cv);
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
} }
} }
} }
@ -169,7 +166,7 @@ public class EventImpl implements Event {
new String[] { Integer.toString(this.getId()), Integer.toString(tag.getId()) } new String[] { Integer.toString(this.getId()), Integer.toString(tag.getId()) }
); );
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
} }
} }
} }
@ -197,7 +194,6 @@ public class EventImpl implements Event {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
tags[index++] = new TagImpl( tags[index++] = new TagImpl(
this.db, this.db,
this.queue,
cursor.getInt(0) cursor.getInt(0)
); );
} }
@ -210,12 +206,12 @@ public class EventImpl implements Event {
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Queue{id="); sb.append("Event{id=");
sb.append(this.getId()); sb.append(this.getId());
sb.append(",timestamp="); sb.append(",timestamp=");
sb.append(this.getTimestamp()); sb.append(this.getTimestamp());
sb.append(",message="); sb.append(",comment=");
sb.append(this.getMessage()); sb.append(this.getComment());
sb.append("}"); sb.append("}");
return sb.toString(); return sb.toString();
} }

View file

@ -17,14 +17,12 @@
package art.pegasko.yeeemp.impl; package art.pegasko.yeeemp.impl;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.util.Log; import android.util.Log;
import art.pegasko.yeeemp.base.Event; import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.EventMaker; import art.pegasko.yeeemp.base.EventMaker;
import art.pegasko.yeeemp.base.Queue;
public class EventMakerImpl implements EventMaker { public class EventMakerImpl implements EventMaker {
public static final String TAG = EventMakerImpl.class.getSimpleName(); public static final String TAG = EventMakerImpl.class.getSimpleName();
@ -36,22 +34,51 @@ public class EventMakerImpl implements EventMaker {
} }
@Override @Override
public Event createInQueue(Queue queue) { public Event create() {
synchronized (this.db) { synchronized (this.db) {
try { try {
ContentValues cv = new ContentValues(); ContentValues cv = new ContentValues();
cv.put("queue_id", queue.getId()); cv.put("id", (Integer) null);
long rowId = db.insertOrThrow("event", null, cv); long rowId = db.insertOrThrow("event", null, cv);
return new EventImpl( return new EventImpl(
this.db, this.db,
queue,
(int) rowId (int) rowId
); );
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
} }
return null; return null;
} }
} }
@Override
public void delete(Event event) {
synchronized (this.db) {
try {
// Delete queue <-> event
db.delete(
"queue_event",
"event_id = ?",
new String[] { Integer.toString(event.getId()) }
);
// Delete event <-> tag
db.delete(
"event_tag",
"event_id = ?",
new String[] { Integer.toString(event.getId()) }
);
// Delete event
db.delete(
"event",
"id = ?",
new String[] { Integer.toString(event.getId()) }
);
} catch (SQLiteException e) {
Log.wtf(TAG, e);
}
}
}
} }

View file

@ -27,6 +27,7 @@ import androidx.annotation.NonNull;
import art.pegasko.yeeemp.base.Event; import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.Queue; import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.Tag; import art.pegasko.yeeemp.base.Tag;
import kotlin.NotImplementedError;
public class QueueImpl implements Queue { public class QueueImpl implements Queue {
public static final String TAG = QueueImpl.class.getSimpleName(); public static final String TAG = QueueImpl.class.getSimpleName();
@ -81,16 +82,62 @@ public class QueueImpl implements Queue {
@Override @Override
public Event[] getEvents() { public Event[] getEvents() {
return new Event[0]; synchronized (this.db) {
Cursor cursor = db.query(
"queue_event",
new String[] { "event_id" },
"queue_id = ?",
new String[] { Integer.toString(this.getId()) },
null,
null,
null
);
if (cursor == null) {
return new Event[0];
}
Event[] events = new Event[cursor.getCount()];
int index = 0;
while (cursor.moveToNext()) {
events[index++] = new EventImpl(
this.db,
cursor.getInt(0)
);
}
return events;
}
}
@Override
public int getEventCount() {
synchronized (this.db) {
Cursor cursor = db.query(
"queue_event",
new String[] { "count(*)" },
"queue_id = ?",
new String[] { Integer.toString(this.getId()) },
null,
null,
null
);
if (!Utils.findResult(cursor))
return 0;
return cursor.getInt(0);
}
} }
/** !synchronized */ /** !synchronized */
protected boolean hasEvent(Event event) { protected boolean hasEvent(Event event) {
synchronized (this.db) { synchronized (this.db) {
Cursor cursor = db.query( Cursor cursor = db.query(
"query_event", "queue_event",
new String[] { "1" }, new String[] { "1" },
"query_id = ? AND event_id = ?", "queue_id = ? AND event_id = ?",
new String[] { Integer.toString(this.getId()), Integer.toString(event.getId()) }, new String[] { Integer.toString(this.getId()), Integer.toString(event.getId()) },
null, null,
null, null,
@ -137,7 +184,7 @@ public class QueueImpl implements Queue {
new String[] { Integer.toString(this.getId()), Integer.toString(event.getId()) } new String[] { Integer.toString(this.getId()), Integer.toString(event.getId()) }
); );
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
} }
} }
} }
@ -165,7 +212,6 @@ public class QueueImpl implements Queue {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
tags[index++] = new TagImpl( tags[index++] = new TagImpl(
this.db, this.db,
this,
cursor.getInt(0) cursor.getInt(0)
); );
} }

View file

@ -22,6 +22,8 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.util.Log; import android.util.Log;
import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.EventMaker;
import art.pegasko.yeeemp.base.Queue; import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.QueueMaker; import art.pegasko.yeeemp.base.QueueMaker;
@ -34,6 +36,31 @@ public class QueueMakerImpl implements QueueMaker {
this.db = db; this.db = db;
} }
@Override
public Queue getById(int id) {
synchronized (this.db) {
try {
Cursor cursor = db.query(
"queue",
new String[] { "1" },
"id = ?",
new String[] { Integer.toString(id) },
null,
null,
null
);
if (Utils.findResult(cursor))
return new QueueImpl(this.db, id);
} catch (SQLiteException e) {
Log.wtf(TAG, e);
}
return null;
}
}
@Override @Override
public Queue create() { public Queue create() {
synchronized (this.db) { synchronized (this.db) {
@ -46,7 +73,7 @@ public class QueueMakerImpl implements QueueMaker {
(int) rowId (int) rowId
); );
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
} }
return null; return null;
@ -83,4 +110,46 @@ public class QueueMakerImpl implements QueueMaker {
return queues; return queues;
} }
} }
@Override
public void delete(Queue queue) {
synchronized (this.db) {
// Drop events
try {
for (Event event: queue.getEvents()) {
db.delete(
"event",
"id = ?",
new String[] { Integer.toString(event.getId()) }
);
}
} catch (SQLiteException e) {
Log.wtf(TAG, e);
return;
}
// Drop queue <-> event
try {
db.delete(
"queue_event",
"queue_id = ?",
new String[] { Integer.toString(queue.getId()) }
);
} catch (SQLiteException e) {
Log.wtf(TAG, e);
}
// Drop queue
try {
db.delete(
"queue",
"id = ?",
new String[] { Integer.toString(queue.getId()) }
);
} catch (SQLiteException e) {
Log.wtf(TAG, e);
}
}
}
} }

View file

@ -28,12 +28,10 @@ public class TagImpl implements Tag {
public static final String TAG = TagImpl.class.getSimpleName(); public static final String TAG = TagImpl.class.getSimpleName();
private final SQLiteDatabase db; private final SQLiteDatabase db;
private final Queue queue;
private final int id; private final int id;
protected TagImpl(SQLiteDatabase db, Queue queue, int id) { protected TagImpl(SQLiteDatabase db, int id) {
this.db = db; this.db = db;
this.queue = queue;
this.id = id; this.id = id;
} }
@ -48,8 +46,8 @@ public class TagImpl implements Tag {
Cursor cursor = db.query( Cursor cursor = db.query(
"tag", "tag",
new String[] { "name" }, new String[] { "name" },
"query_id = ? AND id = ?", "id = ?",
new String[] { Integer.toString(queue.getId()), Integer.toString(this.getId()) }, new String[] { Integer.toString(this.getId()) },
null, null,
null, null,
null null

View file

@ -41,7 +41,7 @@ public class TagMakerImpl implements TagMaker {
Cursor cursor = db.query( Cursor cursor = db.query(
"tag", "tag",
new String[] { "id", "name" }, new String[] { "id", "name" },
"query_id = ? AND name = ?", "queue_id = ? AND name = ?",
new String[] { Integer.toString(queue.getId()), name }, new String[] { Integer.toString(queue.getId()), name },
null, null,
null, null,
@ -50,12 +50,11 @@ public class TagMakerImpl implements TagMaker {
if (Utils.findResult(cursor)) { if (Utils.findResult(cursor)) {
return new TagImpl( return new TagImpl(
db, db,
queue,
cursor.getInt(0) cursor.getInt(0)
); );
} }
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
} }
return null; return null;
@ -69,7 +68,7 @@ public class TagMakerImpl implements TagMaker {
cv.put("name", name); cv.put("name", name);
db.insertOrThrow("tag", null, cv); db.insertOrThrow("tag", null, cv);
} catch (SQLiteException e) { } catch (SQLiteException e) {
Log.w(TAG, e); Log.wtf(TAG, e);
return false; return false;
} }
return true; return true;

View file

@ -0,0 +1,112 @@
/**
* Copyright 2024 pegasko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art.pegasko.yeeemp.ui.activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.snackbar.Snackbar;
import art.pegasko.yeeemp.R;
import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.Wrapper;
import art.pegasko.yeeemp.databinding.ActivityEventListBinding;
import art.pegasko.yeeemp.impl.Init;
public class EventListActivity extends AppCompatActivity {
public static final String TAG = EventListActivity.class.getSimpleName();
private ActivityEventListBinding binding;
private RecyclerView eventList;
private EventRecyclerViewAdapter eventListAdapter;
private Queue queue;
private void updateList() {
runOnUiThread(() -> {
eventListAdapter.reloadItems();
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Init.initDB(getApplicationContext());
// Get Queue ID from Intent
Bundle extras = getIntent().getExtras();
if (extras == null) {
Log.e(TAG, "Missing Intent arguments (queue_id)");
finish();
return;
}
int queue_id = extras.getInt("queue_id", -1);
if (queue_id == -1) {
Log.e(TAG, "Missing Intent arguments (queue_id)");
finish();
return;
}
queue = Wrapper.getQueueMaker().getById(queue_id);
if (queue == null) {
Log.e(TAG, "Missing Intent arguments (queue_id)");
finish();
return;
}
binding = ActivityEventListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
/* Queue list */
eventListAdapter = new EventRecyclerViewAdapter(queue);
eventList = findViewById(R.id.content_event_list__list);
eventList.setLayoutManager(new LinearLayoutManager(this));
eventList.setAdapter(eventListAdapter);
/* FAB Listeners */
binding.fab.setOnLongClickListener((View view) -> {
Snackbar.make(view, "Create Event", Snackbar.LENGTH_LONG)
.setAnchorView(R.id.fab)
.setAction("Action", null).show();
return true;
});
binding.fab.setOnClickListener(view -> {
Log.w(TAG, "TODO: Open editor");
Event event = Wrapper.getEventMaker().create();
event.setTimestamp(System.currentTimeMillis());
event.setComment("Lobster number " + System.currentTimeMillis());
queue.addEvent(event);
Log.w(TAG, "Create: " + event.toString() + " in " + queue);
updateList();
});
/* Fill lists */
updateList();
}
}

View file

@ -0,0 +1,117 @@
/**
* Copyright 2024 pegasko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art.pegasko.yeeemp.ui.activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.PopupMenu;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import art.pegasko.yeeemp.R;
import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.Wrapper;
import art.pegasko.yeeemp.databinding.EventListItemBinding;
import art.pegasko.yeeemp.databinding.QueueListItemBinding;
class EventRecyclerViewAdapter extends RecyclerView.Adapter<EventRecyclerViewAdapter.ViewHolder> {
public static final String TAG = EventRecyclerViewAdapter.class.getSimpleName();
private final Queue queue;
private Event[] events;
public EventRecyclerViewAdapter(Queue queue) {
super();
this.queue = queue;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View view = (
LayoutInflater
.from(viewGroup.getContext())
.inflate(R.layout.event_list_item, viewGroup, false)
);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
viewHolder.getBinding().eventListItemTimestamp.setText(Utils.formatTs(events[position].getTimestamp()));
viewHolder.getBinding().eventListItemItem.setOnLongClickListener((View view) -> {
PopupMenu popupMenu = new PopupMenu(view.getContext(), viewHolder.getBinding().eventListItemItem);
popupMenu.getMenuInflater().inflate(R.menu.event_list_item_action_menu, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener((MenuItem menuItem) -> {
if (menuItem.getItemId() == R.id.event_list_item_action_menu_delete) {
new AlertDialog.Builder(view.getContext())
.setTitle("Delete event")
.setMessage("Are you sure you want to delete this event?")
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
Wrapper.getEventMaker().delete(events[position]);
reloadItems();
})
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
return true;
});
popupMenu.show();
return true;
});
// viewHolder.queueStats.setText(Integer.toString(events[position].getEventCount()));
}
@Override
public int getItemCount() {
return this.events.length;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private EventListItemBinding binding;
public ViewHolder(@NonNull View itemView) {
super(itemView);
this.binding = EventListItemBinding.bind(itemView);
}
public EventListItemBinding getBinding() {
return this.binding;
}
}
public void reloadItems() {
this.events = this.queue.getEvents();
this.notifyDataSetChanged();
}
}

View file

@ -1,61 +0,0 @@
/**
* Copyright 2024 pegasko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art.pegasko.yeeemp.ui.activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import art.pegasko.yeeemp.R;
import art.pegasko.yeeemp.databinding.FragmentFirstBinding;
public class FirstFragment extends Fragment {
private FragmentFirstBinding binding;
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentFirstBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonFirst.setOnClickListener(v ->
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment)
);
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View file

@ -22,26 +22,23 @@ import androidx.appcompat.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import art.pegasko.yeeemp.base.Queue; import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.Wrapper; import art.pegasko.yeeemp.base.Wrapper;
import art.pegasko.yeeemp.databinding.ActivityMainBinding; import art.pegasko.yeeemp.databinding.ActivityQueueListBinding;
import art.pegasko.yeeemp.R; import art.pegasko.yeeemp.R;
import art.pegasko.yeeemp.impl.EventImpl;
import art.pegasko.yeeemp.impl.Init; import art.pegasko.yeeemp.impl.Init;
public class MainActivity extends AppCompatActivity { public class QueueListActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName(); public static final String TAG = QueueListActivity.class.getSimpleName();
private AppBarConfiguration appBarConfiguration; private AppBarConfiguration appBarConfiguration;
private ActivityMainBinding binding; private ActivityQueueListBinding binding;
private RecyclerView queueList; private RecyclerView queueList;
private QueueRecyclerViewAdapter queueListAdapter; private QueueRecyclerViewAdapter queueListAdapter;
@ -57,20 +54,16 @@ public class MainActivity extends AppCompatActivity {
Init.initDB(getApplicationContext()); Init.initDB(getApplicationContext());
binding = ActivityMainBinding.inflate(getLayoutInflater()); binding = ActivityQueueListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar); setSupportActionBar(binding.toolbar);
/* Queue list */
queueListAdapter = new QueueRecyclerViewAdapter(); queueListAdapter = new QueueRecyclerViewAdapter();
queueList = findViewById(R.id.content_main__queue_list); queueList = findViewById(R.id.content_queue_list__list);
queueList.setLayoutManager(new LinearLayoutManager(this)); queueList.setLayoutManager(new LinearLayoutManager(this));
queueList.setAdapter(queueListAdapter); queueList.setAdapter(queueListAdapter);
// NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
// appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
// NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
/* FAB Listeners */ /* FAB Listeners */
binding.fab.setOnLongClickListener((View view) -> { binding.fab.setOnLongClickListener((View view) -> {
Snackbar.make(view, "Create Queue", Snackbar.LENGTH_LONG) Snackbar.make(view, "Create Queue", Snackbar.LENGTH_LONG)
@ -79,25 +72,23 @@ public class MainActivity extends AppCompatActivity {
return true; return true;
}); });
binding.fab.setOnClickListener(new View.OnClickListener() { binding.fab.setOnClickListener(view -> {
@Override Queue q = Wrapper.getQueueMaker().create();
public void onClick(View view) { q.setName("New Queue");
Queue q = Wrapper.getQueueMaker().create(); Log.w(TAG, "Create: " + q.toString());
q.setName("New Queue");
Log.w(TAG, "Create: " + q.toString());
updateList(); updateList();
}
}); });
/* Fill lists */ /* Fill lists */
updateList(); updateList();
} }
// @Override @Override
// public boolean onSupportNavigateUp() { protected void onResume() {
// NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); super.onResume();
// return NavigationUI.navigateUp(navController, appBarConfiguration)
// || super.onSupportNavigateUp(); /* Ekchualle we returned from somewhere */
// } updateList();
}
} }

View file

@ -1,7 +1,25 @@
/**
* Copyright 2024 pegasko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art.pegasko.yeeemp.ui.activity; package art.pegasko.yeeemp.ui.activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType; import android.text.InputType;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -10,19 +28,17 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import art.pegasko.yeeemp.R; import art.pegasko.yeeemp.R;
import art.pegasko.yeeemp.base.Event;
import art.pegasko.yeeemp.base.Queue; import art.pegasko.yeeemp.base.Queue;
import art.pegasko.yeeemp.base.QueueMaker;
import art.pegasko.yeeemp.base.Wrapper; import art.pegasko.yeeemp.base.Wrapper;
import art.pegasko.yeeemp.impl.EventImpl; import art.pegasko.yeeemp.databinding.QueueListItemBinding;
public class QueueRecyclerViewAdapter extends RecyclerView.Adapter<QueueRecyclerViewAdapter.ViewHolder> { class QueueRecyclerViewAdapter extends RecyclerView.Adapter<QueueRecyclerViewAdapter.ViewHolder> {
public static final String TAG = QueueRecyclerViewAdapter.class.getSimpleName(); public static final String TAG = QueueRecyclerViewAdapter.class.getSimpleName();
private Queue[] queues; private Queue[] queues;
@ -41,20 +57,20 @@ public class QueueRecyclerViewAdapter extends RecyclerView.Adapter<QueueRecycler
@Override @Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
viewHolder.queueName.setText(queues[position].getName()); viewHolder.getBinding().queueListItemTitle.setText(queues[position].getName());
viewHolder.queueItem.setOnLongClickListener((View view) -> {
PopupMenu popupMenu = new PopupMenu(view.getContext(), viewHolder.queueItem); viewHolder.getBinding().queueListItemItem.setOnLongClickListener((View view) -> {
PopupMenu popupMenu = new PopupMenu(view.getContext(), viewHolder.getBinding().queueListItemItem);
popupMenu.getMenuInflater().inflate(R.menu.queue_list_item_action_menu, popupMenu.getMenu()); popupMenu.getMenuInflater().inflate(R.menu.queue_list_item_action_menu, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener((MenuItem menuItem) -> { popupMenu.setOnMenuItemClickListener((MenuItem menuItem) -> {
if (menuItem.getItemId() == R.id.queue_list_item_action_menu_delete) { if (menuItem.getItemId() == R.id.queue_list_item_action_menu_delete) {
new AlertDialog.Builder(view.getContext()) new AlertDialog.Builder(view.getContext())
.setTitle("Delete entry") .setTitle("Delete queue")
.setMessage("Are you sure you want to delete this queue?") .setMessage("Are you sure you want to delete this queue?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { .setPositiveButton(android.R.string.yes, (dialog, which) -> {
public void onClick(DialogInterface dialog, int which) { Wrapper.getQueueMaker().delete(queues[position]);
// Wrapper.getQueueMaker().delete
Log.e(TAG, "Not implemented action"); reloadItems();
}
}) })
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
@ -85,6 +101,30 @@ public class QueueRecyclerViewAdapter extends RecyclerView.Adapter<QueueRecycler
return true; return true;
}); });
viewHolder.getBinding().queueListItemItem.setOnClickListener((View view) -> {
Bundle extra = new Bundle();
extra.putInt("queue_id", queues[position].getId());
Intent intent = new Intent(view.getContext(), EventListActivity.class);
intent.putExtras(extra);
view.getContext().startActivity(intent);
});
viewHolder.getBinding().queueListItemStats.setText(Integer.toString(queues[position].getEventCount()));
viewHolder.getBinding().queueListItemPlus.setOnClickListener((View view) -> {
Log.w(TAG, "TODO: Open editor");
Event event = Wrapper.getEventMaker().create();
event.setTimestamp(System.currentTimeMillis());
event.setComment("Lobster number " + System.currentTimeMillis());
queues[position].addEvent(event);
Log.w(TAG, "Create: " + event.toString() + " in " + queues[position]);
reloadItems();
});
} }
@Override @Override
@ -93,18 +133,15 @@ public class QueueRecyclerViewAdapter extends RecyclerView.Adapter<QueueRecycler
} }
public static class ViewHolder extends RecyclerView.ViewHolder { public static class ViewHolder extends RecyclerView.ViewHolder {
private TextView queueName; private QueueListItemBinding binding;
private View queueItem;
public ViewHolder(@NonNull View itemView) { public ViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
this.binding = QueueListItemBinding.bind(itemView);
queueItem = itemView.findViewById(R.id.queue_list_item__queue_item);
queueName = (TextView) itemView.findViewById(R.id.queue_list_item__queue_title);
} }
public TextView getQueueName() { public QueueListItemBinding getBinding() {
return queueName; return this.binding;
} }
} }

View file

@ -1,61 +0,0 @@
/**
* Copyright 2024 pegasko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art.pegasko.yeeemp.ui.activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import art.pegasko.yeeemp.R;
import art.pegasko.yeeemp.databinding.FragmentSecondBinding;
public class SecondFragment extends Fragment {
private FragmentSecondBinding binding;
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentSecondBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(v ->
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment)
);
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View file

@ -0,0 +1,29 @@
/**
* Copyright 2024 pegasko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art.pegasko.yeeemp.ui.activity;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Utils {
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static String formatTs(long timestamp) {
SimpleDateFormat sdf = new SimpleDateFormat(Utils.DATE_FORMAT);
return sdf.format(timestamp);
}
}

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp" android:width="108dp"

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp" android:width="108dp"

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">

View file

@ -0,0 +1,53 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ui.activity.QueueListActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextColor="@color/pegasko_white"
android:background="@color/pegasko_dark" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_event_list"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_input_add"
android:backgroundTint="@color/pegasko_blue" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
@ -6,7 +22,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
tools:context=".ui.activity.MainActivity"> tools:context=".ui.activity.QueueListActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -22,7 +38,7 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main"/> <include layout="@layout/content_queue_list"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab" android:id="@+id/fab"
@ -32,6 +48,6 @@
android:layout_marginEnd="@dimen/fab_margin" android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_input_add" app:srcCompat="@android:drawable/ic_input_add"
android:backgroundTint="?attr/colorPrimary" /> android:backgroundTint="@color/pegasko_green" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,10 +1,26 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorSecondary" android:background="@color/pegasko_black"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@ -15,6 +31,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:padding="@dimen/pegasko_list_item_content_margin" android:padding="@dimen/pegasko_list_item_content_margin"
android:id="@+id/content_main__queue_list" /> android:id="@+id/content_event_list__list" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,36 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/pegasko_black"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="@dimen/pegasko_list_item_content_margin"
android:id="@+id/content_queue_list__list" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,75 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<LinearLayout
android:id="@+id/event_list_item__item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/pegasko_list_item_content_margin"
android:layout_weight="1"
android:background="@color/pegasko_blue"
android:gravity="center"
android:padding="@dimen/pegasko_list_item_main_padding">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/event_list_item__timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/pegasko_list_item_title_margin"
android:fontFamily="monospace"
android:text="TextView"
android:textAlignment="viewStart"
android:textColor="@color/pegasko_black"
android:textSize="@dimen/pegasko_list_item_title"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="@dimen/pegasko_list_item_plus_width"
android:layout_height="match_parent"
android:layout_margin="@dimen/pegasko_list_item_content_margin"
android:background="@color/pegasko_blue"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:text="+"
android:textAlignment="viewStart"
android:textColor="@color/pegasko_black"
android:textSize="@dimen/pegasko_list_item_plus"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>

View file

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<Button
android:id="@+id/button_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"
app:layout_constraintBottom_toTopOf="@id/textview_first"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/lorem_ipsum"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button_first" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<Button
android:id="@+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/previous"
app:layout_constraintBottom_toTopOf="@id/textview_second"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/lorem_ipsum"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button_second" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -1,34 +1,73 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/pegasko_list_item_size" android:layout_height="wrap_content"
android:background="@android:color/transparent" > android:background="@android:color/transparent">
<LinearLayout <LinearLayout
android:id="@+id/queue_list_item__item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/queue_list_item__queue_item"
android:layout_margin="@dimen/pegasko_list_item_content_margin" android:layout_margin="@dimen/pegasko_list_item_content_margin"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/pegasko_green" android:background="@color/pegasko_green"
android:gravity="center"> android:gravity="center"
android:padding="@dimen/pegasko_list_item_main_padding">
<TextView <LinearLayout
android:id="@+id/queue_list_item__queue_title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="monospace" android:gravity="center"
android:text="TextView" android:orientation="vertical">
android:textAlignment="viewStart"
android:textColor="@color/pegasko_black" <TextView
android:textSize="@dimen/pegasko_list_item_title" android:id="@+id/queue_list_item__title"
android:textStyle="bold" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/pegasko_list_item_title_margin"
android:fontFamily="monospace"
android:text="TextView"
android:textAlignment="viewStart"
android:textColor="@color/pegasko_black"
android:textSize="@dimen/pegasko_list_item_title"
android:textStyle="bold" />
<TextView
android:id="@+id/queue_list_item__stats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/pegasko_list_item_subtitle_margin"
android:fontFamily="monospace"
android:text="TextView"
android:textAlignment="viewStart"
android:textColor="@color/pegasko_black"
android:textSize="@dimen/pegasko_list_item_subtitle"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="@dimen/pegasko_list_item_size" android:id="@+id/queue_list_item__plus"
android:layout_width="@dimen/pegasko_list_item_plus_width"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="@dimen/pegasko_list_item_content_margin" android:layout_margin="@dimen/pegasko_list_item_content_margin"
android:background="@color/pegasko_green" android:background="@color/pegasko_green"

View file

@ -0,0 +1,22 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/event_list_item_action_menu_delete"
android:title="Delete" />
</menu>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item <item

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" /> <background android:drawable="@drawable/ic_launcher_background" />

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" /> <background android:drawable="@drawable/ic_launcher_background" />

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_graph"
app:startDestination="@id/FirstFragment">
<fragment
android:id="@+id/FirstFragment"
android:name="art.pegasko.yeeemp.ui.FirstFragment"
android:label="@string/first_fragment_label"
tools:layout="@layout/fragment_first">
<action
android:id="@+id/action_FirstFragment_to_SecondFragment"
app:destination="@id/SecondFragment" />
</fragment>
<fragment
android:id="@+id/SecondFragment"
android:name="art.pegasko.yeeemp.ui.SecondFragment"
android:label="@string/second_fragment_label"
tools:layout="@layout/fragment_second">
<action
android:id="@+id/action_SecondFragment_to_FirstFragment"
app:destination="@id/FirstFragment" />
</fragment>
</navigation>

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_graph2"
app:startDestination="@id/FirstFragment">
<fragment
android:id="@+id/FirstFragment"
android:name="art.pegasko.yeeemp.ui.activity.FirstFragment"
android:label="@string/first_fragment_label"
tools:layout="@layout/fragment_first" >
<action
android:id="@+id/action_FirstFragment_to_SecondFragment"
app:destination="@id/SecondFragment" />
</fragment>
<fragment
android:id="@+id/SecondFragment"
android:name="art.pegasko.yeeemp.ui.activity.SecondFragment"
android:label="@string/second_fragment_label"
tools:layout="@layout/fragment_second" >
<action
android:id="@+id/action_SecondFragment_to_FirstFragment"
app:destination="@id/FirstFragment" />
</fragment>
</navigation>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources> <resources>
<dimen name="fab_margin">48dp</dimen> <dimen name="fab_margin">48dp</dimen>
</resources> </resources>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.Yeeemp.Green" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <style name="Theme.Yeeemp.Green" parent="Theme.MaterialComponents.DayNight.DarkActionBar">

View file

@ -1,7 +1,23 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Yeeemp.Green" parent="Base.Theme.Yeeemp.Green"> <style name="Theme.Yeeemp.Green" parent="Base.Theme.Yeeemp.Green">
<item name="android:navigationBarColor">@color/pegasko_dark_green</item> <item name="android:navigationBarColor">@color/pegasko_dark</item>
<item name="android:statusBarColor">@color/pegasko_dark_green</item> <item name="android:statusBarColor">@color/pegasko_dark</item>
<item name="android:windowLightStatusBar">false</item> <item name="android:windowLightStatusBar">false</item>
</style> </style>
</resources> </resources>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources> <resources>
<dimen name="fab_margin">200dp</dimen> <dimen name="fab_margin">200dp</dimen>
</resources> </resources>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources> <resources>
<dimen name="fab_margin">48dp</dimen> <dimen name="fab_margin">48dp</dimen>
</resources> </resources>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>

View file

@ -1,9 +1,35 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources> <resources>
<dimen name="fab_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen>
<dimen name="pegasko_list_item_size">80dp</dimen> <dimen name="pegasko_list_item_size">80dp</dimen>
<dimen name="pegasko_list_item_padding">8dp</dimen> <dimen name="pegasko_list_item_padding">8dp</dimen>
<dimen name="pegasko_list_item_main_padding">8dp</dimen>
<dimen name="pegasko_list_item_title">24sp</dimen> <dimen name="pegasko_list_item_title">24sp</dimen>
<dimen name="pegasko_list_item_title_margin">4dp</dimen>
<dimen name="pegasko_list_item_subtitle">12sp</dimen>
<dimen name="pegasko_list_item_subtitle_margin">2dp</dimen>
<dimen name="pegasko_list_item_plus">32sp</dimen> <dimen name="pegasko_list_item_plus">32sp</dimen>
<dimen name="pegasko_list_item_plus_width">80dp</dimen>
<dimen name="pegasko_list_item_content_margin">2dp</dimen> <dimen name="pegasko_list_item_content_margin">2dp</dimen>
</resources> </resources>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources> <resources>
<string name="app_name">Yeeemp</string> <string name="app_name">Yeeemp</string>
<!-- Strings used for fragments for navigation --> <!-- Strings used for fragments for navigation -->

View file

@ -1,6 +1,22 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.Yeeemp" parent="Theme.MaterialComponents.DayNight"> <style name="Theme.Yeeemp" parent="ThemeOverlay.MaterialComponents.Dark">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/pegasko_white</item> <item name="colorPrimary">@color/pegasko_white</item>
<item name="colorPrimaryVariant">@color/pegasko_light</item> <item name="colorPrimaryVariant">@color/pegasko_light</item>
@ -18,7 +34,7 @@
</style> </style>
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Base.Theme.Yeeemp" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Base.Theme.Yeeemp" parent="Theme.Material3.Dark.NoActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/pegasko_white</item> <item name="colorPrimary">@color/pegasko_white</item>
<item name="colorPrimaryVariant">@color/pegasko_light</item> <item name="colorPrimaryVariant">@color/pegasko_light</item>

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?><!-- <?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary. Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup See https://developer.android.com/guide/topics/data/autobackup

View file

@ -1,3 +1,19 @@
<!--
Copyright 2024 pegasko
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml version="1.0" encoding="utf-8"?><!-- <?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary. Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes See https://developer.android.com/about/versions/12/backup-restore#xml-changes