Skip to content

Commit

Permalink
add basic timeout animation
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamVe committed Oct 18, 2023
1 parent ef7e810 commit 0565beb
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 18 deletions.
5 changes: 4 additions & 1 deletion apps/gtkmm/include/timer_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ class TimerWidget : public Gtk::Widget {
TimerWidget();
~TimerWidget() override;

void setTimeStep(int ts);

protected:
void measure_vfunc(Gtk::Orientation orientation, int for_size, int& minimum, int& natural,
int& minimum_baseline, int& natural_baseline) const override;
void snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot) override;

Gtk::Border padding;
Gdk::RGBA foregroundColor { 0.0, 0.0, 0.0 };
int timeStep;
long lastUpdateMs;
};
} // authppgtk
13 changes: 12 additions & 1 deletion apps/gtkmm/src/app_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,17 @@ AppWindow::AppWindow(BaseObjectType* baseObjectType, const Glib::RefPtr<Gtk::Bui
list_item->set_data("name", builder->get_widget<Gtk::Label>("name"));
list_item->set_data("issuer", builder->get_widget<Gtk::Label>("issuer"));
list_item->set_data("code", builder->get_widget<Gtk::Label>("code"));
builder->get_widget<Gtk::Box>("toprow")->append(*Gtk::make_managed<TimerWidget>());
auto timer = Gtk::make_managed<TimerWidget>();
builder->get_widget<Gtk::Box>("toprow")->append(*timer);
list_item->set_data("timer", timer);
list_item->set_child(*accountWidget);
});
factory->signal_bind().connect([](const Glib::RefPtr<Gtk::ListItem>& list_item) {
auto* const name = static_cast<Gtk::Label*>(list_item->get_data("name"));
auto* const issuer = static_cast<Gtk::Label*>(list_item->get_data("issuer"));
auto* const code = static_cast<Gtk::Label*>(list_item->get_data("code"));


auto holder = std::dynamic_pointer_cast<AccountHolder>(list_item->get_item());

std::string issuerValue;
Expand All @@ -62,6 +65,14 @@ AppWindow::AppWindow(BaseObjectType* baseObjectType, const Glib::RefPtr<Gtk::Bui
name->set_text(nameValue);
issuer->set_text(issuerValue);
code->set_text(holder->account.code.value);

auto* const timer = static_cast<TimerWidget*>(list_item->get_data("timer"));
if (holder->account.code.type == authpp::oath::Type::TOTP) {
timer->setTimeStep(holder->account.timeStep);
timer->set_visible(true);
} else {
timer->set_visible(false);
}
});

refreshButton->signal_clicked().connect(sigc::mem_fun(*this, &AppWindow::requestAccounts));
Expand Down
61 changes: 45 additions & 16 deletions apps/gtkmm/src/timer_widget.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
#include "timer_widget.h"

#include <libauthpp/logger.h>
#include <libauthpp/time_util.h>

#include <gdkmm/frameclock.h>
#include <gdkmm/general.h>

#include <gtkmm/snapshot.h>

namespace authppgtk {

namespace {
authpp::Logger log("TimerWidget");
}

TimerWidget::TimerWidget()
{
set_expand(false);

padding.set_left(0);
padding.set_right(0);
padding.set_top(0);
padding.set_bottom(0);
timeStep = 0;
lastUpdateMs = 0L;

add_tick_callback([this](const auto& clock) {
auto currentFrameTime = clock->get_frame_time() / 1000;
if (currentFrameTime > lastUpdateMs + 200) {
queue_draw();
lastUpdateMs = currentFrameTime;
}
return true;
});
}

TimerWidget::~TimerWidget() = default;

void TimerWidget::setTimeStep(int ts) { this->timeStep = ts; }

void TimerWidget::measure_vfunc(Gtk::Orientation orientation, int /* for_size */, int& minimum,
int& natural, int& minimum_baseline, int& natural_baseline) const
{
Expand All @@ -27,27 +46,37 @@ void TimerWidget::measure_vfunc(Gtk::Orientation orientation, int /* for_size */

void TimerWidget::snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot)
{
auto toRad = [](double deg) -> double {
auto degToRad = [](double deg) -> double {
auto d = deg - 90;
if (d < 0) {
d = 360 + d;
}
return d * M_PI / 180.0;
};

auto currentMillis = authpp::TimeUtil::getCurrentMilliSeconds();
auto currentSeconds = currentMillis / 1000;

auto ts = authpp::TimeUtil::getTotpTimeStep(currentSeconds, timeStep);

const auto allocation = get_allocation();
const Gdk::Rectangle rect(0, 0, allocation.get_width(), allocation.get_height());
const auto width = allocation.get_width();
const auto width_2 = width / 2.0;
const auto height = allocation.get_height();
const auto height_2 = height / 2.0;
const Gdk::Rectangle rect(0, 0, width, height);
auto cr = snapshot->append_cairo(rect);
cr->set_antialias(Cairo::ANTIALIAS_SUBPIXEL);
Gdk::Cairo::set_source_rgba(cr, foregroundColor);
cr->translate(padding.get_left(), padding.get_top());
cr->move_to(allocation.get_width() / 2.0, allocation.get_height() / 2.0);
cr->arc_negative(allocation.get_width() / 2.0, allocation.get_height() / 2.0,
allocation.get_height() / 2.0 - 2, toRad(0), toRad(90));
cr->move_to(allocation.get_width() / 2.0, allocation.get_height() / 2.0);
cr->fill();
cr->arc(allocation.get_width() / 2.0, allocation.get_height() / 2.0,
allocation.get_height() / 2.0 - 2, 0, 2 * M_PI);

if (currentSeconds < ((ts + 1) * timeStep)) {
auto accountDelayMs = (double)(currentMillis - ts * timeStep * 1000);
auto deg = (360.0 / (timeStep * 1000)) * (accountDelayMs - 1500);
Gdk::Cairo::set_source_rgba(cr, foregroundColor);
cr->move_to(width_2, height_2);
cr->arc_negative(width_2, height_2, height_2 - 2, degToRad(0), degToRad(deg));
cr->move_to(width_2, height_2);
cr->fill();
}
cr->arc(width_2, height_2, height_2 - 2, 0, 2 * M_PI);
cr->stroke();
}

Expand Down

0 comments on commit 0565beb

Please sign in to comment.