Compare commits
	
		
			7 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9a0df4f577 | |||
| 61714836bb | |||
| cff0c100ec | |||
| 010c49d100 | |||
| ff5dbaffc0 | |||
| b56d581e4b | |||
| aa661aaaa7 | 
							
								
								
									
										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, prev_tm.tm_mon, prev_tm.tm_mday,
 | 
			
		||||
											1900+next_tm.tm_year, 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...
 | 
			
		||||
 | 
			
		||||
@@ -275,7 +275,7 @@ Screen* MainScreen::render(float time_delta, bool&) {
 | 
			
		||||
	struct PerfProfileRender {
 | 
			
		||||
		float low_delay_window {1.5f};
 | 
			
		||||
		float low_delay_min {1.f/60.f};
 | 
			
		||||
		float low_delay_max {1.f/30.f};
 | 
			
		||||
		float low_delay_max {1.f/60.f};
 | 
			
		||||
 | 
			
		||||
		float mid_delay_window {30.f};
 | 
			
		||||
		float mid_delay_min {1.f/60.f};
 | 
			
		||||
@@ -289,7 +289,7 @@ Screen* MainScreen::render(float time_delta, bool&) {
 | 
			
		||||
	const static PerfProfileRender normalPerfProfile{
 | 
			
		||||
		//1.5f,		// low_delay_window
 | 
			
		||||
		//1.f/60.f,	// low_delay_min
 | 
			
		||||
		//1.f/30.f,	// low_delay_max
 | 
			
		||||
		//1.f/60.f,	// low_delay_max
 | 
			
		||||
 | 
			
		||||
		//30.f,		// mid_delay_window
 | 
			
		||||
		//1.f/60.f,	// mid_delay_min
 | 
			
		||||
 
 | 
			
		||||
@@ -94,7 +94,7 @@ struct MainScreen final : public Screen {
 | 
			
		||||
	// 0 - normal
 | 
			
		||||
	// 1 - reduced
 | 
			
		||||
	// 2 - power save
 | 
			
		||||
	int _fps_perf_mode {1};
 | 
			
		||||
	int _fps_perf_mode {0};
 | 
			
		||||
	// 0 - normal
 | 
			
		||||
	// 1 - power save
 | 
			
		||||
	int _compute_perf_mode {0};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user