Skip to content

Commit 32ff0b5

Browse files
authored
[image_picker] Refactor the C++ code (#353)
1 parent c75dce5 commit 32ff0b5

File tree

5 files changed

+347
-303
lines changed

5 files changed

+347
-303
lines changed

packages/image_picker/tizen/src/image_picker_tizen_plugin.cc

Lines changed: 101 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@
55
#include "image_picker_tizen_plugin.h"
66

77
#include <app_control.h>
8-
#include <assert.h>
98
#include <flutter/method_channel.h>
109
#include <flutter/plugin_registrar.h>
1110
#include <flutter/standard_method_codec.h>
12-
#ifndef TV_PROFILE
13-
#include <privacy_privilege_manager.h>
14-
#endif
1511

12+
#include <cassert>
1613
#include <memory>
1714
#include <string>
15+
#include <variant>
1816

1917
#include "image_resize.h"
20-
#include "log.h"
18+
#include "permission_manager.h"
19+
20+
namespace {
2121

2222
enum class ImageSource {
2323
// Opens up the device camera, letting the user to take a new picture.
@@ -26,6 +26,19 @@ enum class ImageSource {
2626
kGallery,
2727
};
2828

29+
template <typename T>
30+
static bool GetValueFromEncodableMap(const flutter::EncodableMap *map,
31+
const char *key, T &out) {
32+
auto iter = map->find(flutter::EncodableValue(key));
33+
if (iter != map->end() && !iter->second.IsNull()) {
34+
if (auto *value = std::get_if<T>(&iter->second)) {
35+
out = *value;
36+
return true;
37+
}
38+
}
39+
return false;
40+
}
41+
2942
class ImagePickerTizenPlugin : public flutter::Plugin {
3043
public:
3144
static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar) {
@@ -53,176 +66,119 @@ class ImagePickerTizenPlugin : public flutter::Plugin {
5366
const flutter::MethodCall<flutter::EncodableValue> &method_call,
5467
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
5568
const auto &method_name = method_call.method_name();
56-
const auto &arguments = *method_call.arguments();
5769

5870
if (result_) {
59-
SendResultWithError("Already active", "Cancelled by a second request.");
71+
SendErrorResult("Already active", "Cancelled by a second request.");
6072
return;
6173
}
6274
result_ = std::move(result);
63-
multi_image_ = method_name == "pickMultiImage";
6475

65-
ImageSource source = ImageSource::kGallery;
6676
if (method_name == "pickImage" || method_name == "pickMultiImage") {
67-
double width = 0.0, height = 0.0;
77+
const auto *arguments =
78+
std::get_if<flutter::EncodableMap>(method_call.arguments());
79+
assert(arguments);
80+
81+
int source_index = static_cast<int>(ImageSource::kGallery);
82+
double max_width = 0.0, max_height = 0.0;
6883
int32_t quality = 0;
69-
if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
70-
flutter::EncodableMap values =
71-
std::get<flutter::EncodableMap>(arguments);
72-
auto s = values[flutter::EncodableValue("source")];
73-
if (std::holds_alternative<int32_t>(s)) {
74-
source = (ImageSource)std::get<int32_t>(s);
75-
}
76-
auto w = values[flutter::EncodableValue("maxWidth")];
77-
if (std::holds_alternative<double>(w)) {
78-
width = std::get<double>(w);
79-
}
80-
auto h = values[flutter::EncodableValue("maxHeight")];
81-
if (std::holds_alternative<double>(h)) {
82-
height = std::get<double>(h);
83-
}
84-
auto q = values[flutter::EncodableValue("imageQuality")];
85-
if (std::holds_alternative<int32_t>(q)) {
86-
quality = std::get<int32_t>(q);
87-
}
88-
image_resize_.SetSize((unsigned int)width, (unsigned int)height,
89-
quality);
90-
} else {
91-
SendResultWithError("Invalid arguments");
92-
return;
93-
}
84+
GetValueFromEncodableMap(arguments, "source", source_index);
85+
GetValueFromEncodableMap(arguments, "maxWidth", max_width);
86+
GetValueFromEncodableMap(arguments, "maxHeight", max_height);
87+
GetValueFromEncodableMap(arguments, "imageQuality", quality);
9488

89+
image_resize_.SetSize(static_cast<uint32_t>(max_width),
90+
static_cast<uint32_t>(max_height), quality);
91+
92+
ImageSource source = ImageSource(source_index);
9593
if (source == ImageSource::kCamera) {
9694
// TODO: we need to check this feature after webcam is prepared
97-
SendResultWithError("Not supported on this device");
95+
SendErrorResult("Not supported", "Not supported on this device.");
9896
} else if (source == ImageSource::kGallery) {
99-
SetContentMimeType("image");
100-
CheckPermissionAndPickContent();
97+
multi_image_ = method_name == "pickMultiImage";
98+
PickContent("image/*");
10199
} else {
102-
SendResultWithError("Invalid image source");
100+
SendErrorResult("Invalid arguments", "Invalid image source.");
103101
}
104102
} else if (method_name == "pickVideo") {
105-
if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
106-
flutter::EncodableMap values =
107-
std::get<flutter::EncodableMap>(arguments);
108-
auto s = values[flutter::EncodableValue("source")];
109-
if (std::holds_alternative<int32_t>(s)) {
110-
source = (ImageSource)std::get<int32_t>(s);
111-
}
112-
} else {
113-
SendResultWithError("Invalid arguments");
114-
return;
115-
}
103+
const auto *arguments =
104+
std::get_if<flutter::EncodableMap>(method_call.arguments());
105+
assert(arguments);
106+
107+
int source_index = static_cast<int>(ImageSource::kGallery);
108+
GetValueFromEncodableMap(arguments, "source", source_index);
116109

110+
ImageSource source = ImageSource(source_index);
117111
if (source == ImageSource::kCamera) {
118112
// TODO: we need to check this feature after webcam is prepared
119-
SendResultWithError("Not supported on this device");
113+
SendErrorResult("Not supported", "Not supported on this device.");
120114
} else if (source == ImageSource::kGallery) {
121-
SetContentMimeType("video");
122-
CheckPermissionAndPickContent();
115+
PickContent("video/*");
123116
} else {
124-
SendResultWithError("Invalid video source");
117+
SendErrorResult("Invalid arguments", "Invalid video source.");
125118
}
126119
} else {
127120
result_->NotImplemented();
128121
result_ = nullptr;
129122
}
130123
}
131124

132-
void CheckPermissionAndPickContent() {
133-
#ifndef TV_PROFILE
134-
const char *privilege = "http://tizen.org/privilege/mediastorage";
135-
136-
ppm_check_result_e permission;
137-
int ret = ppm_check_permission(privilege, &permission);
138-
if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
139-
LOG_ERROR("ppm_check_permission fail! [%d]", ret);
140-
} else {
141-
switch (permission) {
142-
case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
143-
LOG_INFO("ppm_check_permission success!");
144-
PickContent();
145-
return;
146-
case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
147-
ret = ppm_request_permission(
148-
privilege,
149-
[](ppm_call_cause_e cause, ppm_request_result_e result,
150-
const char *privilege, void *data) -> void {
151-
auto *plugin = (ImagePickerTizenPlugin *)data;
152-
assert(plugin);
153-
154-
if (cause == PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR) {
155-
LOG_ERROR("ppm_request_permission error! [%d]", result);
156-
plugin->SendResultWithError("Permission denied");
157-
return;
158-
}
159-
if (result !=
160-
PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER) {
161-
LOG_ERROR("ppm_request_permission deny! [%d]", result);
162-
plugin->SendResultWithError("Permission denied");
163-
return;
164-
}
165-
166-
plugin->PickContent();
167-
},
168-
this);
169-
if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
170-
LOG_ERROR("ppm_request_permission fail! [%d]", ret);
171-
break;
172-
}
173-
return;
174-
default:
175-
LOG_ERROR("ppm_check_permission deny!");
176-
break;
177-
}
125+
bool CheckPermission() {
126+
PermissionManager manager;
127+
PermissionResult result =
128+
manager.RequestPermssion("http://tizen.org/privilege/mediastorage");
129+
130+
if (result == PermissionResult::kDenyForever ||
131+
result == PermissionResult::kDenyOnce) {
132+
SendErrorResult("Permission denied", "Permission denied by user.");
133+
return false;
134+
} else if (result == PermissionResult::kError) {
135+
SendErrorResult("Operation failed", "Failed to request permission.");
136+
return false;
178137
}
179-
SendResultWithError("Permission denied");
180-
#else
181-
PickContent();
182-
#endif
138+
return true;
183139
}
184140

185-
void PickContent() {
141+
void PickContent(std::string mime_type) {
142+
if (!CheckPermission()) {
143+
return;
144+
}
145+
186146
app_control_h handle = nullptr;
187-
#define RET_IF_ERROR(ret) \
188-
if (ret != APP_CONTROL_ERROR_NONE) { \
189-
SendResultWithError(std::to_string(ret), get_error_message(ret)); \
190-
if (handle) { \
191-
app_control_destroy(handle); \
192-
} \
193-
return; \
147+
#define RETURN_IF_ERROR(ret) \
148+
if (ret != APP_CONTROL_ERROR_NONE) { \
149+
SendErrorResult(std::to_string(ret), get_error_message(ret)); \
150+
if (handle) { \
151+
app_control_destroy(handle); \
152+
} \
153+
return; \
194154
}
195155
int ret = app_control_create(&handle);
196-
RET_IF_ERROR(ret);
156+
RETURN_IF_ERROR(ret);
197157

198158
ret = app_control_set_operation(handle, APP_CONTROL_OPERATION_PICK);
199-
RET_IF_ERROR(ret);
159+
RETURN_IF_ERROR(ret);
200160

201161
ret = app_control_add_extra_data(handle, APP_CONTROL_DATA_SELECTION_MODE,
202162
multi_image_ ? "multiple" : "single");
203-
RET_IF_ERROR(ret);
163+
RETURN_IF_ERROR(ret);
204164

205-
ret = app_control_set_mime(handle, mime_type_.c_str());
206-
RET_IF_ERROR(ret);
165+
ret = app_control_set_mime(handle, mime_type.c_str());
166+
RETURN_IF_ERROR(ret);
207167

208-
ret = app_control_send_launch_request(handle, PickImageReplyCallback, this);
209-
RET_IF_ERROR(ret);
210-
#undef RET_IF_ERROR
168+
ret = app_control_send_launch_request(handle, ReplyCallback, this);
169+
RETURN_IF_ERROR(ret);
170+
#undef RETURN_IF_ERROR
211171

212172
app_control_destroy(handle);
213173
}
214174

215-
static void PickImageReplyCallback(app_control_h request, app_control_h reply,
216-
app_control_result_e result,
217-
void *user_data) {
218-
LOG_INFO("PickImageReplyCallback called: %d", (int)result);
219-
220-
auto *plugin = (ImagePickerTizenPlugin *)user_data;
221-
assert(plugin != nullptr);
222-
assert(plugin->result_ != nullptr);
175+
static void ReplyCallback(app_control_h request, app_control_h reply,
176+
app_control_result_e result, void *user_data) {
177+
auto *self = static_cast<ImagePickerTizenPlugin *>(user_data);
178+
assert(self->result_);
223179

224180
if (result != APP_CONTROL_RESULT_SUCCEEDED) {
225-
plugin->SendResultWithError("Operation failed");
181+
self->SendErrorResult("Operation failed", "Received an error response.");
226182
return;
227183
}
228184

@@ -231,32 +187,32 @@ class ImagePickerTizenPlugin : public flutter::Plugin {
231187
int ret = app_control_get_extra_data_array(reply, APP_CONTROL_DATA_SELECTED,
232188
&values, &count);
233189
if (ret != APP_CONTROL_ERROR_NONE) {
234-
plugin->SendResultWithError(std::to_string(ret), get_error_message(ret));
190+
self->SendErrorResult(std::to_string(ret), get_error_message(ret));
235191
return;
236192
}
237193

238194
if (count == 0) {
239-
plugin->SendResultWithError("No file selected");
240-
} else if (plugin->multi_image_) {
195+
self->SendErrorResult("Operation cancelled", "No file selected.");
196+
} else if (self->multi_image_) {
241197
flutter::EncodableList paths;
242198
for (int i = 0; i < count; i++) {
243199
std::string source_path = values[i];
244200
std::string dest_path;
245-
if (plugin->image_resize_.Resize(source_path, dest_path)) {
201+
if (self->image_resize_.Resize(source_path, &dest_path)) {
246202
paths.push_back(flutter::EncodableValue(dest_path));
247203
} else {
248204
paths.push_back(flutter::EncodableValue(source_path));
249205
}
250206
free(values[i]);
251207
}
252-
plugin->SendResultWithSuccess(flutter::EncodableValue(paths));
208+
self->SendResult(flutter::EncodableValue(paths));
253209
} else {
254210
std::string source_path = values[0];
255211
std::string dest_path;
256-
if (plugin->image_resize_.Resize(source_path, dest_path)) {
257-
plugin->SendResultWithSuccess(flutter::EncodableValue(dest_path));
212+
if (self->image_resize_.Resize(source_path, &dest_path)) {
213+
self->SendResult(flutter::EncodableValue(dest_path));
258214
} else {
259-
plugin->SendResultWithSuccess(flutter::EncodableValue(source_path));
215+
self->SendResult(flutter::EncodableValue(source_path));
260216
}
261217
free(values[0]);
262218
}
@@ -266,33 +222,30 @@ class ImagePickerTizenPlugin : public flutter::Plugin {
266222
}
267223
}
268224

269-
void SendResultWithSuccess(const flutter::EncodableValue &result) {
270-
if (result_ == nullptr) {
225+
void SendResult(const flutter::EncodableValue &result) {
226+
if (!result_) {
271227
return;
272228
}
273229
result_->Success(result);
274230
result_ = nullptr;
275231
}
276232

277-
void SendResultWithError(const std::string &error_code,
278-
const std::string &error_message = "") {
279-
if (result_ == nullptr) {
233+
void SendErrorResult(const std::string &error_code,
234+
const std::string &error_message) {
235+
if (!result_) {
280236
return;
281237
}
282238
result_->Error(error_code, error_message);
283239
result_ = nullptr;
284240
}
285241

286-
void SetContentMimeType(const std::string &mime_type) {
287-
mime_type_ = mime_type + "/*";
288-
}
289-
290-
ImageResize image_resize_;
291242
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result_;
292-
std::string mime_type_;
243+
ImageResize image_resize_;
293244
bool multi_image_ = false;
294245
};
295246

247+
} // namespace
248+
296249
void ImagePickerTizenPluginRegisterWithRegistrar(
297250
FlutterDesktopPluginRegistrarRef registrar) {
298251
ImagePickerTizenPlugin::RegisterWithRegistrar(

0 commit comments

Comments
 (0)