Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ on:
tags:
- "v[0-9]+.[0-9]+.[0-9]+**"

pull_request:
branches:
- main

permissions:
contents: write

Expand Down
64 changes: 63 additions & 1 deletion app.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "app.h"
#include <csui/modal.h>
#include <csync/csync.h>
#include <QStyleHints>

const QString help_access_token =
"<span style=\"color: #555555\">"
Expand Down Expand Up @@ -33,6 +34,21 @@ void App::setup_ui()
ui->tree_view->setModel(newTreeModel());
ui->fetch_button->set_states("Fetch", "Fetching...");
ui->pull_button->set_states("Pull", "Pulling...");

ui->theme_selector->addItems({"System theme", "Light theme", "Dark theme"});
const QString saved_theme = settings.get("theme");
const int theme_index = saved_theme == "dark" ? 2 : saved_theme == "light" ? 1 : 0;
ui->theme_selector->setCurrentIndex(theme_index);
connect(ui->theme_selector, &QComboBox::currentTextChanged, this,
[this](const QString &text) {
const QString theme = text.startsWith("Dark") ? "dark" :
text.startsWith("Light") ? "light" : "system";
settings.set("theme", theme);
settings.sync();
apply_theme(theme);
});
apply_theme(saved_theme.isEmpty() ? "system" : saved_theme);

}

void App::connect_ui()
Expand Down Expand Up @@ -329,13 +345,59 @@ void App::show_updates()

void App::check_auth(const QString &token)
{
canvas->set_token(token);
canvas->set_token(token.trimmed());
ui->tree_view->setModel(newTreeModel());
course_trees.clear();
folder_names.clear();
canvas->authenticate();
}

void App::apply_theme(const QString &theme)
{
QPalette palette;
bool dark = theme == "dark";
if (theme == "system") {
dark = QApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark;
}
if (dark) {
palette.setColor(QPalette::Window, QColor("#202020"));
palette.setColor(QPalette::WindowText, Qt::white);
palette.setColor(QPalette::Base, QColor("#2b2b2b"));
palette.setColor(QPalette::AlternateBase, QColor("#353535"));
palette.setColor(QPalette::Text, Qt::white);
palette.setColor(QPalette::Button, QColor("#353535"));
palette.setColor(QPalette::ButtonText, Qt::white);
palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#a8a8a8"));
palette.setColor(QPalette::Highlight, QColor("#3d6f9e"));
palette.setColor(QPalette::HighlightedText, Qt::white);
palette.setColor(QPalette::PlaceholderText, QColor("#b0b0b0"));
} else {
palette = QApplication::style()->standardPalette();
palette.setColor(QPalette::Window, QColor("#f5f5f5"));
palette.setColor(QPalette::Base, Qt::white);
palette.setColor(QPalette::Button, QColor("#e8e8e8"));
palette.setColor(QPalette::Text, QColor("#202020"));
palette.setColor(QPalette::WindowText, QColor("#202020"));
palette.setColor(QPalette::ButtonText, QColor("#202020"));
palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#707070"));
palette.setColor(QPalette::Disabled, QPalette::Text, QColor("#707070"));
palette.setColor(QPalette::HighlightedText, QColor("#202020"));
}
QApplication::setPalette(palette);

const QString foreground = dark ? "#ffffff" : "#202020";
const QString disabled = dark ? "#a8a8a8" : "#707070";
const QString background = dark ? "#353535" : "#e8e8e8";
const QString control_style =
"QPushButton, QComboBox { color: " + foreground +
"; background-color: " + background +
"; } QPushButton:disabled { color: " + disabled + "; }";
ui->change_token_button->setStyleSheet(control_style);
ui->fetch_button->setStyleSheet(control_style);
ui->pull_button->setStyleSheet(control_style);
ui->theme_selector->setStyleSheet(control_style);
}

void App::gather_tracked()
{
prefetch();
Expand Down
1 change: 1 addition & 0 deletions app.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ private slots:
void check_auth(const QString &token);
void gather_tracked();
void ready_all();
void apply_theme(const QString &theme);
TreeModel *newTreeModel();

public:
Expand Down
10 changes: 10 additions & 0 deletions app.ui
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ color: #fbbf24;</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="theme_selector">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
Expand Down
6 changes: 4 additions & 2 deletions lib/convert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ std::vector<T> to_vecq(const QJsonDocument &d,

bool is_valid_profile(const QJsonObject &j)
{
return has(j, "id") && has(j, "name") && has(j, "primary_email") &&
has(j, "login_id") && has(j, "integration_id");
// Canvas may omit optional profile fields such as primary_email and
// integration_id. The API response is authenticated if it contains the
// stable user identity fields we actually need.
return has(j, "id") && has(j, "name");
}

Course to_course(const QJsonObject &j)
Expand Down
12 changes: 8 additions & 4 deletions lib/tree_model.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "tree_model.h"

#include <QApplication>
#include <QPalette>

QVector<QVariant> stringListToVariantList(const QStringList &data)
{
QVector<QVariant> variantData;
Expand Down Expand Up @@ -275,12 +278,13 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const
}

if (role == Qt::ForegroundRole) {
const QPalette palette = qApp->palette();
if (index.column() == TreeIndex::LOCAL_DIR) {
return QVariant(QColor(item->isChecked() && item->has_local_dir()
? Qt::black
: Qt::lightGray));
return QVariant(item->isChecked() && item->has_local_dir()
? palette.color(QPalette::Text)
: palette.color(QPalette::Disabled, QPalette::Text));
}
return QVariant(QColor(Qt::black));
return QVariant(palette.color(QPalette::Text));
}

return QVariant();
Expand Down
1 change: 1 addition & 0 deletions main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);

App w("https://canvas.nus.edu.sg");
w.show();
return a.exec();
Expand Down