Merge remote-tracking branch 'origin/dev' into nfcf

This commit is contained in:
nullableVoidPtr
2022-12-11 11:46:44 +11:00
26 changed files with 292 additions and 129 deletions

View File

@@ -39,7 +39,7 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

View File

@@ -24,7 +24,7 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
@@ -35,6 +35,7 @@ jobs:
mkdir artifacts
- name: 'Get commit details'
id: names
run: |
if [[ ${{ github.event_name }} == 'pull_request' ]]; then
TYPE="pull"
@@ -45,14 +46,6 @@ jobs:
fi
python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
- name: 'Generate suffixes for comment'
id: names
run: |
echo "::set-output name=branch_name::${BRANCH_NAME}"
echo "::set-output name=commit_sha::${COMMIT_SHA}"
echo "::set-output name=default_target::${DEFAULT_TARGET}"
echo "::set-output name=suffix::${SUFFIX}"
- name: 'Bundle scripts'
if: ${{ !github.event.pull_request.head.repo.fork }}
run: |
@@ -143,7 +136,7 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
submodules: true

View File

@@ -20,7 +20,7 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
@@ -36,12 +36,12 @@ jobs:
BRANCHES=$(git branch -r --contains "$SUBMODULE_HASH");
COMMITS_IN_BRANCH="$(git rev-list --count dev)";
if [ $COMMITS_IN_BRANCH -lt $SUB_COMMITS_MIN ]; then
echo "::set-output name=fails::error";
echo "name=fails::error" >> $GITHUB_OUTPUT
echo "::error::Error: Too low commits in $SUB_BRANCH of submodule $SUB_PATH: $COMMITS_IN_BRANCH(expected $SUB_COMMITS_MIN+)";
exit 1;
fi
if ! grep -q "/$SUB_BRANCH" <<< "$BRANCHES"; then
echo "::set-output name=fails::error";
echo "name=fails::error" >> $GITHUB_OUTPUT
echo "::error::Error: Submodule $SUB_PATH is not on branch $SUB_BRANCH";
exit 1;
fi

View File

@@ -23,7 +23,7 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

View File

@@ -20,7 +20,7 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

41
.github/workflows/merge_report.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: 'Check FL ticket in PR name'
on:
push:
branches:
- dev
jobs:
merge_report:
runs-on: [self-hosted,FlipperZeroShell]
steps:
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]; then
git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
fi
- name: 'Checkout code'
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Get commit details'
run: |
if [[ ${{ github.event_name }} == 'pull_request' ]]; then
TYPE="pull"
elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
TYPE="tag"
else
TYPE="other"
fi
python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
- name: 'Check ticket and report'
run: |
FBT_TOOLCHAIN_PATH=/runner/_work source scripts/toolchain/fbtenv.sh
python3 -m pip install slack_sdk
python3 scripts/merge_report_qa.py \
${{ secrets.QA_REPORT_SLACK_TOKEN }} \
${{ secrets.QA_REPORT_SLACK_CHANNEL }}

View File

@@ -25,12 +25,13 @@ jobs:
fi
- name: 'Checkout code'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: 'Get commit details'
id: names
run: |
if [[ ${{ github.event_name }} == 'pull_request' ]]; then
TYPE="pull"
@@ -41,15 +42,6 @@ jobs:
fi
python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
- name: 'Generate suffixes for comment'
if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }}
id: names
run: |
echo "::set-output name=branch_name::${BRANCH_NAME}"
echo "::set-output name=commit_sha::${COMMIT_SHA}"
echo "::set-output name=default_target::${DEFAULT_TARGET}"
echo "::set-output name=suffix::${SUFFIX}"
- name: 'Make reports directory'
run: |
rm -rf reports/

View File

@@ -11,8 +11,14 @@ jobs:
run_units_on_test_bench:
runs-on: [self-hosted, FlipperZeroTest]
steps:
- name: 'Decontaminate previous build leftovers'
run: |
if [ -d .git ]; then
git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
fi
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

View File

@@ -6,7 +6,7 @@
#include <lib/nfc/helpers/mf_classic_dict.h>
#include <lib/digital_signal/digital_signal.h>
#include <lib/nfc/nfc_device.h>
#include <applications/main/nfc/helpers/nfc_generators.h>
#include <lib/nfc/helpers/nfc_generators.h>
#include <lib/flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/file_stream.h>
@@ -102,7 +102,10 @@ static bool nfc_test_digital_signal_test_encode(
do {
// Read test data
if(!nfc_test_read_signal_from_file(file_name)) break;
if(!nfc_test_read_signal_from_file(file_name)) {
FURI_LOG_E(TAG, "Failed to read signal from file");
break;
}
// Encode signal
FURI_CRITICAL_ENTER();

View File

@@ -27,6 +27,7 @@
#include <lib/nfc/nfc_device.h>
#include <lib/nfc/helpers/mf_classic_dict.h>
#include <lib/nfc/parsers/nfc_supported_card.h>
#include <lib/nfc/helpers/nfc_generators.h>
#include "views/dict_attack.h"
#include "views/detect_reader.h"
@@ -63,9 +64,6 @@ typedef enum {
NfcRpcStateEmulated,
} NfcRpcState;
// Forward declaration due to circular dependency
typedef struct NfcGenerator NfcGenerator;
struct Nfc {
NfcWorker* worker;
ViewDispatcher* view_dispatcher;

View File

@@ -1,5 +1,5 @@
#include "../nfc_i.h"
#include "../helpers/nfc_generators.h"
#include "lib/nfc/helpers/nfc_generators.h"
void nfc_scene_generate_info_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = context;
@@ -39,7 +39,12 @@ bool nfc_scene_generate_info_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == DialogExResultRight) {
scene_manager_next_scene(nfc->scene_manager, nfc->generator->next_scene);
// Switch either to NfcSceneMfClassicMenu or NfcSceneMfUltralightMenu
if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicMenu);
} else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu);
}
consumed = true;
}
}

View File

@@ -1,5 +1,5 @@
#include "../nfc_i.h"
#include "../helpers/nfc_generators.h"
#include "lib/nfc/helpers/nfc_generators.h"
enum SubmenuIndex {
SubmenuIndexNFCA4,

View File

@@ -8,7 +8,7 @@
#include <m-array.h>
#define FRAME_HEIGHT 12
#define MAX_LEN_PX 100
#define MAX_LEN_PX 111
#define MENU_ITEMS 4u
#define UNLOCK_CNT 3
@@ -186,7 +186,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
size_t idx = CLAMP((uint16_t)(i + model->list_offset), model->history_item, 0);
item_menu = SubGhzReceiverMenuItemArray_get(model->history->data, idx);
furi_string_set(str_buff, item_menu->item_str);
elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 7 : MAX_LEN_PX);
if(model->idx == idx) {
subghz_view_receiver_draw_frame(canvas, i, scrollbar);
} else {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -99,6 +99,17 @@ bool ws_block_generic_serialize(
break;
}
//DATE AGE set
FuriHalRtcDateTime curr_dt;
furi_hal_rtc_get_datetime(&curr_dt);
uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt);
temp_data = curr_ts;
if(!flipper_format_write_uint32(flipper_format, "Ts", &temp_data, 1)) {
FURI_LOG_E(TAG, "Unable to add timestamp");
break;
}
temp_data = instance->channel;
if(!flipper_format_write_uint32(flipper_format, "Ch", &temp_data, 1)) {
FURI_LOG_E(TAG, "Unable to add Channel");
@@ -168,6 +179,12 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp
}
instance->humidity = (uint8_t)temp_data;
if(!flipper_format_read_uint32(flipper_format, "Ts", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing timestamp");
break;
}
instance->timestamp = (uint32_t)temp_data;
if(!flipper_format_read_uint32(flipper_format, "Ch", (uint32_t*)&temp_data, 1)) {
FURI_LOG_E(TAG, "Missing Channel");
break;

View File

@@ -29,6 +29,7 @@ struct WSBlockGeneric {
uint8_t data_count_bit;
uint8_t battery_low;
uint8_t humidity;
uint32_t timestamp;
uint8_t channel;
uint8_t btn;
float temp;

View File

@@ -8,7 +8,7 @@
#include <m-array.h>
#define FRAME_HEIGHT 12
#define MAX_LEN_PX 100
#define MAX_LEN_PX 112
#define MENU_ITEMS 4u
#define UNLOCK_CNT 3
@@ -189,7 +189,7 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
canvas_set_color(canvas, ColorBlack);
}
canvas_draw_icon(canvas, 4, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]);
canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff));
canvas_draw_str(canvas, 14, 9 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buff));
furi_string_reset(str_buff);
}
if(scrollbar) {

View File

@@ -9,9 +9,11 @@
struct WSReceiverInfo {
View* view;
FuriTimer* timer;
};
typedef struct {
uint32_t curr_ts;
FuriString* protocol_name;
WSBlockGeneric* generic;
} WSReceiverInfoModel;
@@ -28,6 +30,10 @@ void ws_view_receiver_info_update(WSReceiverInfo* ws_receiver_info, FlipperForma
flipper_format_read_string(fff, "Protocol", model->protocol_name);
ws_block_generic_deserialize(model->generic, fff);
FuriHalRtcDateTime curr_dt;
furi_hal_rtc_get_datetime(&curr_dt);
model->curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt);
},
true);
}
@@ -44,46 +50,76 @@ void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) {
"%s %db",
furi_string_get_cstr(model->protocol_name),
model->generic->data_count_bit);
canvas_draw_str(canvas, 5, 8, buffer);
canvas_draw_str(canvas, 0, 8, buffer);
if(model->generic->channel != WS_NO_CHANNEL) {
snprintf(buffer, sizeof(buffer), "Ch: %01d", model->generic->channel);
canvas_draw_str(canvas, 105, 8, buffer);
canvas_draw_str(canvas, 106, 8, buffer);
}
if(model->generic->id != WS_NO_ID) {
snprintf(buffer, sizeof(buffer), "Sn: 0x%02lX", model->generic->id);
canvas_draw_str(canvas, 5, 20, buffer);
canvas_draw_str(canvas, 0, 20, buffer);
}
if(model->generic->btn != WS_NO_BTN) {
snprintf(buffer, sizeof(buffer), "Btn: %01d", model->generic->btn);
canvas_draw_str(canvas, 62, 20, buffer);
canvas_draw_str(canvas, 57, 20, buffer);
}
if(model->generic->battery_low != WS_NO_BATT) {
snprintf(
buffer, sizeof(buffer), "Batt: %s", (!model->generic->battery_low ? "ok" : "low"));
canvas_draw_str(canvas, 90, 20, buffer);
canvas_draw_str_aligned(canvas, 126, 17, AlignRight, AlignCenter, buffer);
}
snprintf(buffer, sizeof(buffer), "Data: 0x%llX", model->generic->data);
canvas_draw_str(canvas, 5, 32, buffer);
canvas_draw_str(canvas, 0, 32, buffer);
elements_bold_rounded_frame(canvas, 2, 37, 123, 25);
elements_bold_rounded_frame(canvas, 0, 38, 127, 25);
canvas_set_font(canvas, FontPrimary);
if(model->generic->temp != WS_NO_TEMPERATURE) {
canvas_draw_icon(canvas, 18, 42, &I_Therm_7x16);
canvas_draw_icon(canvas, 6, 43, &I_Therm_7x16);
snprintf(buffer, sizeof(buffer), "%3.1f C", (double)model->generic->temp);
canvas_draw_str_aligned(canvas, 63, 46, AlignRight, AlignTop, buffer);
canvas_draw_circle(canvas, 55, 45, 1);
canvas_draw_str_aligned(canvas, 47, 47, AlignRight, AlignTop, buffer);
canvas_draw_circle(canvas, 38, 46, 1);
}
if(model->generic->humidity != WS_NO_HUMIDITY) {
canvas_draw_icon(canvas, 75, 42, &I_Humid_10x15);
canvas_draw_icon(canvas, 53, 44, &I_Humid_8x13);
snprintf(buffer, sizeof(buffer), "%d%%", model->generic->humidity);
canvas_draw_str(canvas, 91, 54, buffer);
canvas_draw_str(canvas, 64, 55, buffer);
}
if((int)model->generic->timestamp > 0 && model->curr_ts) {
int ts_diff = (int)model->curr_ts - (int)model->generic->timestamp;
canvas_draw_icon(canvas, 91, 46, &I_Timer_11x11);
if(ts_diff > 60) {
int tmp_sec = ts_diff;
int cnt_min = 1;
for(int i = 1; tmp_sec > 60; i++) {
tmp_sec = tmp_sec - 60;
cnt_min = i;
}
if(model->curr_ts % 2 == 0) {
canvas_draw_str_aligned(canvas, 105, 51, AlignLeft, AlignCenter, "Old");
} else {
if(cnt_min >= 59) {
canvas_draw_str_aligned(canvas, 105, 51, AlignLeft, AlignCenter, "Old");
} else {
snprintf(buffer, sizeof(buffer), "%dm", cnt_min);
canvas_draw_str_aligned(canvas, 114, 51, AlignCenter, AlignCenter, buffer);
}
}
} else {
snprintf(buffer, sizeof(buffer), "%d", ts_diff);
canvas_draw_str_aligned(canvas, 112, 51, AlignCenter, AlignCenter, buffer);
}
}
}
@@ -98,14 +134,19 @@ bool ws_view_receiver_info_input(InputEvent* event, void* context) {
return true;
}
void ws_view_receiver_info_enter(void* context) {
furi_assert(context);
}
void ws_view_receiver_info_exit(void* context) {
static void ws_view_receiver_info_enter(void* context) {
furi_assert(context);
WSReceiverInfo* ws_receiver_info = context;
furi_timer_start(ws_receiver_info->timer, 1000);
}
static void ws_view_receiver_info_exit(void* context) {
furi_assert(context);
WSReceiverInfo* ws_receiver_info = context;
furi_timer_stop(ws_receiver_info->timer);
with_view_model(
ws_receiver_info->view,
WSReceiverInfoModel * model,
@@ -113,6 +154,20 @@ void ws_view_receiver_info_exit(void* context) {
false);
}
static void ws_view_receiver_info_timer(void* context) {
WSReceiverInfo* ws_receiver_info = context;
// Force redraw
with_view_model(
ws_receiver_info->view,
WSReceiverInfoModel * model,
{
FuriHalRtcDateTime curr_dt;
furi_hal_rtc_get_datetime(&curr_dt);
model->curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt);
},
true);
}
WSReceiverInfo* ws_view_receiver_info_alloc() {
WSReceiverInfo* ws_receiver_info = malloc(sizeof(WSReceiverInfo));
@@ -135,12 +190,17 @@ WSReceiverInfo* ws_view_receiver_info_alloc() {
},
true);
ws_receiver_info->timer =
furi_timer_alloc(ws_view_receiver_info_timer, FuriTimerTypePeriodic, ws_receiver_info);
return ws_receiver_info;
}
void ws_view_receiver_info_free(WSReceiverInfo* ws_receiver_info) {
furi_assert(ws_receiver_info);
furi_timer_free(ws_receiver_info->timer);
with_view_model(
ws_receiver_info->view,
WSReceiverInfoModel * model,

View File

@@ -30,7 +30,7 @@ struct ButtonMenu {
typedef struct {
ButtonMenuItemArray_t items;
uint8_t position;
size_t position;
const char* header;
} ButtonMenuModel;
@@ -102,11 +102,9 @@ static void button_menu_view_draw_callback(Canvas* canvas, void* _model) {
ButtonMenuModel* model = (ButtonMenuModel*)_model;
canvas_set_font(canvas, FontSecondary);
uint8_t item_position = 0;
int8_t active_screen = model->position / BUTTONS_PER_SCREEN;
size_t items_size = ButtonMenuItemArray_size(model->items);
int8_t max_screen = ((int16_t)items_size - 1) / BUTTONS_PER_SCREEN;
ButtonMenuItemArray_it_t it;
const size_t active_screen = model->position / BUTTONS_PER_SCREEN;
const size_t items_size = ButtonMenuItemArray_size(model->items);
const size_t max_screen = items_size ? (items_size - 1) / BUTTONS_PER_SCREEN : 0;
if(active_screen > 0) {
canvas_draw_icon(canvas, 28, 1, &I_InfraredArrowUp_4x8);
@@ -125,6 +123,9 @@ static void button_menu_view_draw_callback(Canvas* canvas, void* _model) {
furi_string_free(disp_str);
}
size_t item_position = 0;
ButtonMenuItemArray_it_t it;
for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it);
ButtonMenuItemArray_next(it), ++item_position) {
if(active_screen == (item_position / BUTTONS_PER_SCREEN)) {
@@ -195,14 +196,14 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
if(item) {
if(item->type == ButtonMenuItemTypeControl) {
if(type == InputTypeShort) {
if(item && item->callback) {
if(item->callback) {
item->callback(item->callback_context, item->index, type);
}
}
}
if(item->type == ButtonMenuItemTypeCommon) {
if((type == InputTypePress) || (type == InputTypeRelease)) {
if(item && item->callback) {
if(item->callback) {
item->callback(item->callback_context, item->index, type);
}
}
@@ -341,7 +342,7 @@ void button_menu_set_selected_item(ButtonMenu* button_menu, uint32_t index) {
button_menu->view,
ButtonMenuModel * model,
{
uint8_t item_position = 0;
size_t item_position = 0;
ButtonMenuItemArray_it_t it;
for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it);
ButtonMenuItemArray_next(it), ++item_position) {

View File

@@ -20,8 +20,8 @@ ARRAY_DEF(SubmenuItemArray, SubmenuItem, M_POD_OPLIST);
typedef struct {
SubmenuItemArray_t items;
const char* header;
uint8_t position;
uint8_t window_position;
size_t position;
size_t window_position;
} SubmenuModel;
static void submenu_process_up(Submenu* submenu);
@@ -36,19 +36,19 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
canvas_clear(canvas);
uint8_t position = 0;
SubmenuItemArray_it_t it;
if(model->header) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 4, 11, model->header);
}
canvas_set_font(canvas, FontSecondary);
size_t position = 0;
SubmenuItemArray_it_t it;
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
SubmenuItemArray_next(it)) {
uint8_t item_position = position - model->window_position;
uint8_t items_on_screen = model->header ? 3 : 4;
const size_t item_position = position - model->window_position;
const size_t items_on_screen = model->header ? 3 : 4;
uint8_t y_offset = model->header ? 16 : 0;
if(item_position < items_on_screen) {
@@ -198,7 +198,7 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
submenu->view,
SubmenuModel * model,
{
uint32_t position = 0;
size_t position = 0;
SubmenuItemArray_it_t it;
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
SubmenuItemArray_next(it)) {
@@ -208,7 +208,9 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
position++;
}
if(position >= SubmenuItemArray_size(model->items)) {
const size_t items_size = SubmenuItemArray_size(model->items);
if(position >= items_size) {
position = 0;
}
@@ -219,16 +221,12 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
model->window_position -= 1;
}
uint8_t items_on_screen = model->header ? 3 : 4;
const size_t items_on_screen = model->header ? 3 : 4;
if(SubmenuItemArray_size(model->items) <= items_on_screen) {
if(items_size <= items_on_screen) {
model->window_position = 0;
} else {
if(model->window_position >=
(SubmenuItemArray_size(model->items) - items_on_screen)) {
model->window_position =
(SubmenuItemArray_size(model->items) - items_on_screen);
}
} else if(model->window_position >= items_size - items_on_screen) {
model->window_position = items_size - items_on_screen;
}
},
true);
@@ -239,16 +237,18 @@ void submenu_process_up(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
uint8_t items_on_screen = model->header ? 3 : 4;
const size_t items_on_screen = model->header ? 3 : 4;
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position > 0) {
model->position--;
if(((model->position - model->window_position) < 1) &&
model->window_position > 0) {
if((model->position - model->window_position < 1) &&
(model->window_position > 0)) {
model->window_position--;
}
} else {
model->position = SubmenuItemArray_size(model->items) - 1;
if(model->position > (items_on_screen - 1)) {
model->position = items_size - 1;
if(model->position > items_on_screen - 1) {
model->window_position = model->position - (items_on_screen - 1);
}
}
@@ -261,12 +261,13 @@ void submenu_process_down(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
uint8_t items_on_screen = model->header ? 3 : 4;
if(model->position < (SubmenuItemArray_size(model->items) - 1)) {
const size_t items_on_screen = model->header ? 3 : 4;
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position < items_size - 1) {
model->position++;
if((model->position - model->window_position) > (items_on_screen - 2) &&
model->window_position <
(SubmenuItemArray_size(model->items) - items_on_screen)) {
if((model->position - model->window_position > items_on_screen - 2) &&
(model->window_position < items_size - items_on_screen)) {
model->window_position++;
}
} else {
@@ -284,7 +285,8 @@ void submenu_process_ok(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
if(model->position < (SubmenuItemArray_size(model->items))) {
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position < items_size) {
item = SubmenuItemArray_get(model->items, model->position);
}
},

View File

@@ -81,7 +81,6 @@ FIRMWARE_APPS = {
"basic_services",
"updater_app",
"unit_tests",
"nfc",
],
}

View File

@@ -376,103 +376,86 @@ static void nfc_generate_mf_classic_4k_7b_uid(NfcDeviceData* data) {
static const NfcGenerator mf_ul_generator = {
.name = "Mifare Ultralight",
.generator_func = nfc_generate_mf_ul_orig,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator mf_ul_11_generator = {
.name = "Mifare Ultralight EV1 11",
.generator_func = nfc_generate_mf_ul_11,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator mf_ul_h11_generator = {
.name = "Mifare Ultralight EV1 H11",
.generator_func = nfc_generate_mf_ul_h11,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator mf_ul_21_generator = {
.name = "Mifare Ultralight EV1 21",
.generator_func = nfc_generate_mf_ul_21,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator mf_ul_h21_generator = {
.name = "Mifare Ultralight EV1 H21",
.generator_func = nfc_generate_mf_ul_h21,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag203_generator = {
.name = "NTAG203",
.generator_func = nfc_generate_mf_ul_ntag203,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag213_generator = {
.name = "NTAG213",
.generator_func = nfc_generate_ntag213,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag215_generator = {
.name = "NTAG215",
.generator_func = nfc_generate_ntag215,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag216_generator = {
.name = "NTAG216",
.generator_func = nfc_generate_ntag216,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag_i2c_1k_generator = {
.name = "NTAG I2C 1k",
.generator_func = nfc_generate_ntag_i2c_1k,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag_i2c_2k_generator = {
.name = "NTAG I2C 2k",
.generator_func = nfc_generate_ntag_i2c_2k,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag_i2c_plus_1k_generator = {
.name = "NTAG I2C Plus 1k",
.generator_func = nfc_generate_ntag_i2c_plus_1k,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator ntag_i2c_plus_2k_generator = {
.name = "NTAG I2C Plus 2k",
.generator_func = nfc_generate_ntag_i2c_plus_2k,
.next_scene = NfcSceneMfUltralightMenu,
};
static const NfcGenerator mifare_classic_1k_4b_uid_generator = {
.name = "Mifare Classic 1k 4byte UID",
.generator_func = nfc_generate_mf_classic_1k_4b_uid,
.next_scene = NfcSceneMfClassicMenu,
};
static const NfcGenerator mifare_classic_1k_7b_uid_generator = {
.name = "Mifare Classic 1k 7byte UID",
.generator_func = nfc_generate_mf_classic_1k_7b_uid,
.next_scene = NfcSceneMfClassicMenu,
};
static const NfcGenerator mifare_classic_4k_4b_uid_generator = {
.name = "Mifare Classic 4k 4byte UID",
.generator_func = nfc_generate_mf_classic_4k_4b_uid,
.next_scene = NfcSceneMfClassicMenu,
};
static const NfcGenerator mifare_classic_4k_7b_uid_generator = {
.name = "Mifare Classic 4k 7byte UID",
.generator_func = nfc_generate_mf_classic_4k_7b_uid,
.next_scene = NfcSceneMfClassicMenu,
};
const NfcGenerator* const nfc_generators[] = {

View File

@@ -1,14 +1,13 @@
#pragma once
#include "../nfc_i.h"
#include "../nfc_device.h"
typedef void (*NfcGeneratorFunc)(NfcDeviceData* data);
struct NfcGenerator {
typedef struct {
const char* name;
NfcGeneratorFunc generator_func;
NfcScene next_scene;
};
} NfcGenerator;
extern const NfcGenerator* const nfc_generators[];

View File

@@ -77,28 +77,38 @@ def add_env(name, value, file):
print(f"{delimeter}", file=file)
def add_envs(data, env_file, args):
add_env("COMMIT_MSG", data["commit_comment"], env_file)
add_env("COMMIT_HASH", data["commit_hash"], env_file)
add_env("COMMIT_SHA", data["commit_sha"], env_file)
add_env("SUFFIX", data["suffix"], env_file)
add_env("BRANCH_NAME", data["branch_name"], env_file)
add_env("DIST_SUFFIX", data["suffix"], env_file)
add_env("WORKFLOW_BRANCH_OR_TAG", data["branch_name"], env_file)
def add_set_output_var(name, value, file):
print(f"{name}={value}", file=file)
def add_envs(data, gh_env_file, gh_out_file, args):
add_env("COMMIT_MSG", data["commit_comment"], gh_env_file)
add_env("COMMIT_HASH", data["commit_hash"], gh_env_file)
add_env("COMMIT_SHA", data["commit_sha"], gh_env_file)
add_env("SUFFIX", data["suffix"], gh_env_file)
add_env("BRANCH_NAME", data["branch_name"], gh_env_file)
add_env("DIST_SUFFIX", data["suffix"], gh_env_file)
add_env("WORKFLOW_BRANCH_OR_TAG", data["branch_name"], gh_env_file)
add_set_output_var("branch_name", data["branch_name"], gh_out_file)
add_set_output_var("commit_sha", data["commit_sha"], gh_out_file)
add_set_output_var("default_target", os.getenv("DEFAULT_TARGET"), gh_out_file)
add_set_output_var("suffix", data["suffix"], gh_out_file)
if args.type == "pull":
add_env("PULL_ID", data["pull_id"], env_file)
add_env("PULL_NAME", data["pull_name"], env_file)
add_env("PULL_ID", data["pull_id"], gh_env_file)
add_env("PULL_NAME", data["pull_name"], gh_env_file)
def main():
args = parse_args()
event_file = open(args.event_file)
event_file = open(args.event_file, "r")
event = json.load(event_file)
env_file = open(os.environ["GITHUB_ENV"], "a")
gh_env_file = open(os.environ["GITHUB_ENV"], "a")
gh_out_file = open(os.environ["GITHUB_OUTPUT"], "a")
data = get_details(event, args)
add_envs(data, env_file, args)
add_envs(data, gh_env_file, gh_out_file, args)
event_file.close()
env_file.close()
gh_env_file.close()
gh_out_file.close()
if __name__ == "__main__":

53
scripts/merge_report_qa.py Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import os
import re
import sys
import argparse
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("slack_token")
parser.add_argument("slack_channel")
args = parser.parse_args()
return args
def checkCommitMessage(msg):
regex = re.compile(r"^'?\[FL-\d+\]")
if regex.match(msg):
return True
return False
def reportSlack(commit_hash, slack_token, slack_channel, message):
client = WebClient(token=slack_token)
try:
client.chat_postMessage(channel="#" + slack_channel, text=message)
except SlackApiError as e:
print(e)
sys.exit(1)
def main():
args = parse_args()
commit_msg = os.getenv("COMMIT_MSG")
commit_hash = os.getenv("COMMIT_HASH")
commit_sha = os.getenv("COMMIT_SHA")
commit_link = (
"<https://github.com/flipperdevices/flipperzero-firmware/commit/"
+ commit_hash
+ "|"
+ commit_sha
+ ">"
)
message = "Commit " + commit_link + " merged to dev without 'FL' ticket!"
if not checkCommitMessage(commit_msg):
reportSlack(commit_hash, args.slack_token, args.slack_channel, message)
if __name__ == "__main__":
main()