Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
0aeafec019 | |||
9a0df4f577 | |||
61714836bb | |||
cff0c100ec | |||
010c49d100 | |||
ff5dbaffc0 |
2
external/solanaceae_contact
vendored
2
external/solanaceae_contact
vendored
Submodule external/solanaceae_contact updated: 9ca6adee4f...6f3f9ef191
2
external/solanaceae_message3
vendored
2
external/solanaceae_message3
vendored
Submodule external/solanaceae_message3 updated: a1f5add8d3...c73f727adc
@ -324,6 +324,7 @@ float ChatGui4::render(float time_delta) {
|
||||
//tmp_view.use<Message::Components::Timestamp>();
|
||||
//tmp_view.each([&](const Message3 e, Message::Components::ContactFrom& c_from, Message::Components::ContactTo& c_to, Message::Components::Timestamp ts
|
||||
//) {
|
||||
uint64_t prev_ts {0};
|
||||
auto tmp_view = msg_reg.view<Message::Components::Timestamp>();
|
||||
for (auto view_it = tmp_view.rbegin(), view_last = tmp_view.rend(); view_it != view_last; view_it++) {
|
||||
const Message3 e = *view_it;
|
||||
@ -341,6 +342,34 @@ float ChatGui4::render(float time_delta) {
|
||||
// TODO: why?
|
||||
ImGui::TableNextRow(0, TEXT_BASE_HEIGHT);
|
||||
|
||||
{ // check if date changed
|
||||
// TODO: find defined ways of casting to time_t
|
||||
std::time_t prev = prev_ts / 1000;
|
||||
std::time_t next = ts.ts / 1000;
|
||||
std::tm prev_tm = *std::localtime(&prev);
|
||||
std::tm next_tm = *std::localtime(&next);
|
||||
if (
|
||||
prev_tm.tm_yday != next_tm.tm_yday ||
|
||||
prev_tm.tm_year != next_tm.tm_year // making sure
|
||||
) {
|
||||
// name
|
||||
if (ImGui::TableNextColumn()) {
|
||||
//ImGui::TextDisabled("---");
|
||||
}
|
||||
// msg
|
||||
if (ImGui::TableNextColumn()) {
|
||||
ImGui::TextDisabled("DATE CHANGED from %d.%d.%d to %d.%d.%d",
|
||||
1900+prev_tm.tm_year, 1+prev_tm.tm_mon, prev_tm.tm_mday,
|
||||
1900+next_tm.tm_year, 1+next_tm.tm_mon, next_tm.tm_mday
|
||||
);
|
||||
}
|
||||
ImGui::TableNextRow(0, TEXT_BASE_HEIGHT);
|
||||
}
|
||||
|
||||
prev_ts = ts.ts;
|
||||
}
|
||||
|
||||
|
||||
ImGui::PushID(entt::to_integral(e));
|
||||
|
||||
// name
|
||||
@ -737,7 +766,11 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
||||
) {
|
||||
if (ImGui::Button("save to")) {
|
||||
_fss.requestFile(
|
||||
[](const auto& path) -> bool { return std::filesystem::is_directory(path); },
|
||||
[](std::filesystem::path& path) -> bool {
|
||||
// remove file path
|
||||
path.remove_filename();
|
||||
return std::filesystem::is_directory(path);
|
||||
},
|
||||
[this, ®, e](const auto& path) {
|
||||
if (reg.valid(e)) { // still valid
|
||||
// TODO: trim file?
|
||||
|
@ -18,7 +18,7 @@ FileSelector::FileSelector(void) {
|
||||
}
|
||||
|
||||
void FileSelector::requestFile(
|
||||
std::function<bool(const std::filesystem::path& path)>&& is_valid,
|
||||
std::function<bool(std::filesystem::path& path)>&& is_valid,
|
||||
std::function<void(const std::filesystem::path& path)>&& on_choose,
|
||||
std::function<void(void)>&& on_cancel
|
||||
) {
|
||||
@ -77,7 +77,9 @@ void FileSelector::render(void) {
|
||||
if (current_path.has_parent_path()) {
|
||||
if (ImGui::TableNextColumn()) {
|
||||
if (ImGui::Selectable("D##..", false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap)) {
|
||||
_current_file_path = _current_file_path.parent_path();
|
||||
// the first "parent_path()" only removes the filename and the ending "/"
|
||||
_current_file_path = _current_file_path.parent_path().parent_path() / "";
|
||||
//_current_file_path = _current_file_path.remove_filename().parent_path() / "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ struct FileSelector {
|
||||
|
||||
bool _open_popup {false};
|
||||
|
||||
std::function<bool(const std::filesystem::path& path)> _is_valid = [](auto){ return true; };
|
||||
std::function<bool(std::filesystem::path& path)> _is_valid = [](auto){ return true; };
|
||||
std::function<void(const std::filesystem::path& path)> _on_choose = [](auto){};
|
||||
std::function<void(void)> _on_cancel = [](){};
|
||||
|
||||
@ -18,8 +18,9 @@ struct FileSelector {
|
||||
FileSelector(void);
|
||||
|
||||
// TODO: supply hints
|
||||
// HACK: until we supply hints, is_valid can modify
|
||||
void requestFile(
|
||||
std::function<bool(const std::filesystem::path& path)>&& is_valid,
|
||||
std::function<bool(std::filesystem::path& path)>&& is_valid,
|
||||
std::function<void(const std::filesystem::path& path)>&& on_choose,
|
||||
std::function<void(void)>&& on_cancel
|
||||
);
|
||||
|
72
src/fragment_store/README.md
Normal file
72
src/fragment_store/README.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Fragment Store
|
||||
|
||||
Fragments are are pieces of information split into Metadata and Data.
|
||||
They can be stored seperated or together.
|
||||
They can be used as a Transport protocol/logic too.
|
||||
|
||||
# Store types
|
||||
|
||||
### Object Store
|
||||
|
||||
Fragment files are stored with the first 2 hex chars as sub folders:
|
||||
eg:
|
||||
`objects/` (object store root)
|
||||
- `5f/` (first 2hex subfolder)
|
||||
- `4fffffff` (the fragment file without the first 2 hexchars)
|
||||
|
||||
### Split Object Store
|
||||
|
||||
Same as Object Store, but medadata and data stored in seperate files.
|
||||
Metadata files have the `.meta` suffix. They also have a filetype specific suffix, like `.json`, `.msgpack` etc.
|
||||
|
||||
### Memory Store
|
||||
|
||||
Just keeps the Fragments in memory.
|
||||
|
||||
# File formats
|
||||
|
||||
Files can be compressed and encrypted. Since compression needs the data structure to funcion, it is applied before it is encrypted.
|
||||
|
||||
### Text Json
|
||||
|
||||
Text json only makes sense for metadata if it's neither compressed nor encrypted. (otherwise its binary on disk anyway, so why waste bytes).
|
||||
Since the content of data is not looked at, nothing stops you from using text json and ecrypt it, but atleast basic compression is advised.
|
||||
|
||||
A Metadata json object has the following keys:
|
||||
- `enc` (uint) Encryption type of the data, if any
|
||||
- `comp` (uint) Compression type of the data, if any
|
||||
- `metadata` (obj) the
|
||||
|
||||
## Binary file headers
|
||||
|
||||
### Split Metadata
|
||||
|
||||
file magic bytes `SOLMET` (6 bytes)
|
||||
|
||||
1 byte encryption type (`0x00` is none)
|
||||
|
||||
1 byte compression type (`0x00` is none)
|
||||
|
||||
...metadata here...
|
||||
|
||||
note that the encryption and compression are for the metadata only.
|
||||
The metadata itself contains encryption and compression info about the data.
|
||||
|
||||
### Split Data
|
||||
|
||||
(none) all the data is in the metadata file.
|
||||
This is mostly to allow direct storage for files in the Fragment store without excessive duplication.
|
||||
Keep in mind to not use the actual file name as the data/meta file name.
|
||||
|
||||
### Single fragment
|
||||
|
||||
file magic bytes `SOLFIL` (6 bytes)
|
||||
|
||||
1 byte encryption type (`0x00` is none)
|
||||
|
||||
1 byte compression type (`0x00` is none)
|
||||
|
||||
...metadata here...
|
||||
|
||||
...data here...
|
||||
|
Reference in New Issue
Block a user