Unable to open URL: maps:0,0?q=XX,XX - ios

I got a lot of these errors in production: "Unable to open URL: maps:0,0?q=XX,XX". All are from iOS v16.x, on different devices.
My links are created this way:
const MapLink = ({ coords, label, style, type = 'tDF' }: Props) => {
const { theme } = useTheme();
const [can, setCan] = useState<boolean>();
const url = useMemo(
() =>
coords
? `${Platform.select({
ios: 'maps',
android: 'geo',
})}:0,0?q=${coords.latitude},${coords.longitude}`
: '',
[coords],
);
useEffect(() => {
coords
? Linking.canOpenURL(url)
.then(r => setCan(r))
.catch(() => setCan(false))
: setCan(false);
}, [coords]);
return can && coords && coords.latitude && coords.longitude ? (
<Button
bgColor={theme.color.textL}
type={'underline'}
size={'sm'}
label={label ?? ''}
onPress={() => Linking.openURL(url).then()}
style={style}
/>
) : label ? (
<Typo type={type} text={label} color={theme.color.text} />
) : null;
};
I can't reproduce it neither on Simulator, neither on a real device.
Before activate the link, I check with canOpenURL, so I don't understand how it's possibile that 1) A simple map link is not openable 2) canOpenURL should return true to activate the link, so why the error then?

Try this:
<View>
{
can && coords && coords.latitude && coords.longitude ? (
<Button
bgColor={theme.color.textL}
type={'underline'}
size={'sm'}
label={label ?? ''}
onPress={() => Linking.openURL(url).then()}
style={style}
/>
) :label ? (
<Typo type={type} text={label} color={theme.color.text} />
) :null
}
</View>

Related

How to Remove Specific Query Filter From url in nextJS Application

i'm trying to add product filtering functionality like this: filter product image and after add filter i have to clear filter as user wish like this one: clear filter image if anyone give me real world idea with some more details or short word it can help me be more proffessional.
Well let's assume your filters data is like this:
[
{
catrgory: "Color",
values: [
"Silver",
"Black",
...
]
},
{
catrgory: "Material",
values: [
"Acrylic",
"Rayon",
...
]
},
...
]
You should have 2 states in your component. One for holding the filters data and another for holding the selected filters.
Fetch your filters data from the server once. (Or use a local file).
Each time the user selects a filter, you should add it to your selected filters data.
Each time the user remove a filter, you should remove it from your selected filters data.
Hope it helps (It's just a guide not the whole solution):
const MyComponent = () => {
const [filtersData, setFiltersData] = useState([]);
const [selectedFilters, setSelectedFilters] = useState([]);
useEffect(() => {
// fetch data from the server
}, []);
const handleSelectFilter = (category, value) => {
const newSelectedFilters = [...selectedFilters];
let filter = newSelectedFilters.find((selectedFilter) => selectedFilter.category === category);
if(filter) {
filter.values.push(value);
} else {
filter = {
catrgoty: category,
values: [value]
}
newSelectedFilters.push(filter);
}
setSelectedFilters(newSelectedFilters);
}
const handleDeleteFilter = (category, value) => {
let newSelectedFilters = [...selectedFilters];
const index = newSelectedFilters.findIndex((selectedFilter) => selectedFilter.category === category);
newSelectedFilters = newSelectedFilters.splice(index, 1);
setSelectedFilters(newSelectedFilters);
}
return (
<div>
{
filtersData.map((filterItem, index) => {
return (
<div key={index}>
<div>{filterItem.category}</div>
{
filterItem.values.map((value) => {
return (
<div key={value} onClick={() => handleSelectFilter(filterItem.category, value)}>{value}</div>
)
})
}
</div>
)
})
}
{
selectedFilters.map((selectedFilter, index) => {
return (
<div key={index}>
<div>{selectedFilter.category}</div>
{
selectedFilter.values.map((value) => {
return (
<div key={value} onClick={() => handleDeleteFilter(filterItem.category, value)}>{value}</div>
)
})
}
</div>
)
})
}
</div>
);
}

Expo Image Picker With Rails API gets Errno::ENOENT (No such file or directory # rb_sysopen

When I try to upload image via Expo's: ImagePicker I get:
Completed 500 Internal Server Error in 1ms (ActiveRecord: 2.8ms | Allocations: 637)
Errno::ENOENT (No such file or directory # rb_sysopen - file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540zilasino%252Frestaurant-management/ImagePicker/5f29f45c-4467-4360-bcc8-2651146837b3.jpg):
It does work fine when I hit the endpoint via Insomnia, the image is uploaded, but it doesn't work doing so via expo app running on Android Emulator. It seems like, the data is passing to rails, but for some reason rails is unable to find that file... Any ideas?
CreateMenuItem.js
const addMenuItem = async () => {
const menuItem = {
name,
price,
image: selectedImage.uri,
is_drink: isDrink ? true : false,
notes,
};
const resp = await createAccessory("menu_items", menuItem);
if(resp.type == 'success'){
fetchMenuItemData();
clearFields()
}
showMessage({
message: `${resp.msg}`,
position: "center",
duration: 2500,
style: { backgroundColor: resp.type == 'success' ? colors.PRIMARY : colors.ERROR },
titleStyle: { fontSize: 20 },
});
};
const createAccessory = async (accessory, payload) => {
return await axios.post(baseUrl + '/' + accessory, payload, {headers})
.then(resp => {
if (resp.data){
return { msg: i18n.t('saved'), type: 'success' }
} })
.catch(error => {
if (error.response) {
return { msg: error.response.data.name }
}
}
)
}
ImageUpload.js
const ImageUpload = ({ parentCallback, selectedImage }) => {
let openImagePickerAsync = async () => {
let permissionResult =
await ImagePicker.requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
alert("Permission to access camera roll is required!");
return;
}
let pickerResult = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1
});
if (pickerResult.cancelled === true) {
return;
}
parentCallback(pickerResult);
};
if (selectedImage != null) {
return (
<>
<Image
source={{ uri: selectedImage.uri }}
style={styles.thumbnail}
resizeMode="contain"
/>
<Button
title="X"
color={colors.PRIMARY}
onPress={() => parentCallback(null)}
/>
</>
);
} else {
return (
<>
<TouchableOpacity onPress={openImagePickerAsync} style={styles.button}>
<Text style={styles.buttonText}>{i18n.t("pickAnImage")}</Text>
</TouchableOpacity>
</>
);
}
};
controller.rb
class MenuItemsController < ApplicationController
...
def create
image = Cloudinary::Uploader.upload(params[:image])
menu_item = MenuItem.new(
image: image['url'],
)
end
...
end
One possible issue could be that the path to the image file is incorrect. Try double-checking the path and make sure that the image file is in the correct location.
I figured it out, I had to pass the image to Rails as a Base64 and not just its URI.
I've just added base64: true option:
let pickerResult = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
base64: true
})
and change one line in rails controller like so:
image = Cloudinary::Uploader.upload('data:image/jpeg;base64,' + menu_item_params[:image])

How to dynamically disable the button of antd modal using button props

I have an antd Modal, i am trying to validate a field and provided validation to it. How can i enable/disable the Ok button based on the validation. If the validation is successful then button should be enabled else disabled.
<Form>
<Modal
title={modalHeader}
okText="ADD FIELD"
cancelText="CANCEL"
visible={visible}
onCancel={onCancelHandler}
onOk={() => onAddFieldHandler(fieldName)}
width={600}
okButtonProps={{disabled:true}}
>
<p>Please provide name</p>
<Form.Item
name="fieldName"
rules={[{ required: true, message: 'Please enter name' }]}
>
<FieldNameInput
placeholder="Field name..."
value={fieldName}
onChange={(event) => setFieldName(event.target.value)}
/>
</Form.Item>
</Modal>
</Form>
You can use onFieldsChange from Antd Forms API togehter with geFieldsError and the okButtonProps from Antd Modal API.
const [form] = Form.useForm();
const [buttonDisabled, setButtonDisabled] = useState(true);
return (
<Modal
...
okButtonProps={{ disabled: buttonDisabled }}
>
<Form
form={form}
...
onFieldsChange={() =>
setButtonDisabled(
form.getFieldsError().some((field) => field.errors.length > 0)
)
}
>
Here is a working Stackblitz.
In my case I had Form inside modal and there is onFieldChange prop when you can pass function to perform some operations due to changes on from so you can sth like that:
const SomeModal = ({ visible }) => {
const [form] = Form.useForm();
const [buttonDisabled, setButtonDisabled] = useState(true);
const handleOk = () => form.submit();
const handleAfterClose = () => {
setButtonDisabled(true);
form.resetFields();
}
const handleCancel = () => ...some action to hide modal;
const handleFormFinish = (values) => {
... some logic here
}
return (
<Modal
title={"Some title..."}
visible={visibile}
onOk={handleOk}
onCancel={handleCancel}
afterClose={handleAfterClose}
okButtonProps={{ disabled: buttonDisabled }}
>
<Form
form={form}
layout="vertical"
name="acceptform"
onFinish={handleFormFinish}
initialValues={{
...initial values here
}}
onFieldsChange={() => {
const actualFieldValues = form.getFieldsValue();
const anyError = form.getFieldsError().some((field) => field.errors.length > 0);
.. some logic if error etc..
if (anyError) {
setButtonDisabled(true);
}
else {
setButtonDisabled(false);
}
}}
>
and of course there is need to have some validators on fields
<Form.Item
label={"someLabel"}
id="field"
name="field"
hasFeedback
rules={[
{
type: "string",
validator: async (rule, value) => inputFieldValidate(value, "custom message")
},
]}
>
and validator looks alike:
const inputFieldValidate = async (value, message) => {
if (someCondition)) {
return Promise.reject(message);
}
return Promise.resolve();
};
here is some nice to know that validator isasync and to make it work without any warnings just handle promises
Having the Form inside the Modal, a way to update modal button status would be just running form instance's validateFields, but there are two things to take into account:
This function is a Promise, so the state must update after an await with the validation results.
I've experienced some looping issues when using onFieldsChange (maybe the validation triggers some kind of field update). Instead, onValuesChange has worked good enough for me.
Running the validation into a setTimeout callback seems to be mandatory. Doing it without the setTimeout returns a validation error even when all the fields are valid because of an outOfDate: true. It seems to be because of how the Antd Form update lifecycle works, and waiting until this process has ended (what we can easily achieve with the setTimeout) solves that problem.
A succesful validation returns the form values object, a failed one returns an errorInfo object with the errors list, the outOfDate status and the current form values. You can use the errors list in the latter to get the validation messages returned by Antd to display more descriptive and specific feedback.
In the end, my approach has this structure:
const MyModal = ({onFinish, ...otherProps}) => {
const [canSubmit, setCanSubmit] = useState(false);
const [form] = Form.useForm();
return (
<Modal
{...otherProps}
okButtonProps={{
disabled: !canSubmit
}}
>
<MyFormComponent
form={form}
onFinish={onFinish}
onValuesChange={() => {
setTimeout(() => {
form
.validateFields()
.then(() => {
/*
values:
{
username: 'username',
password: 'password',
}
*/
setCanSubmit(true);
})
.catch((err) => {
/*
errorInfo:
{
values: {
username: 'username',
password: 'password',
},
errorFields: [
{ name: ['password'], errors: ['Please input your Password!'] },
],
outOfDate: false,
}
*/
setCanSubmit(false);
});
});
}}
/>
</Modal>
);
};

App not authenticated with Firebase. Permission Denied error

I have been following this guide to add and retrieve items from firebase using React Native. If I set my rules on firebase to public, everything works but if I set it to the following, I get a permission denied error.
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
I have added all of my config data properly in my ios.js. Is there some basic step that I am missing here?
index.ios.js:
// Initialize Firebase
const firebaseConfig = {
apiKey: 'myapikey',
authDomain: 'myauthdomain',
databaseURL: 'https://url.firebaseio.com',
projectId: 'myProjectId',
storageBucket: 'projectid.appspot.com',
messagingSenderId: 'myMessagingSenderId'
};
const firebaseApp = firebase.initializeApp(firebaseConfig);
class MyNewAppreactold extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
})
};
this.itemsRef = this.getRef().child('items');
}
getRef() {
return firebaseApp.database().ref();
}
listenForItems(itemsRef) {
itemsRef.on('value', (snap) => {
// get children as an array
var items = [];
snap.forEach((child) => {
items.push({
title: child.val().title,
_key: child.key
});
});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(items)
});
});
}
// componentWillMount() {
// firebase.initializeApp(firebaseConfig);
// }
componentDidMount() {
this.listenForItems(this.itemsRef);
}
render() {
return (
<View style={styles.container}>
<StatusBar title="Grocery List" />
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderItem.bind(this)}
enableEmptySections={true}
style={styles.listview}/>
<ActionButton onPress={this._addItem.bind(this)} title="Add" />
</View>
)
}
_addItem() {
AlertIOS.prompt(
'Add New Item',
null,
[
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{
text: 'Add',
onPress: (text) => {
this.itemsRef.push({ title: text })
}
},
],
'plain-text'
);
}
_renderItem(item) {
const onPress = () => {
AlertIOS.alert(
'Complete',
null,
[
{text: 'Complete', onPress: (text) => this.itemsRef.child(item._key).remove()},
{text: 'Cancel', onPress: (text) => console.log('Cancelled')}
]
);
};
return (
<ListItem item={item} onPress={onPress} />
);
}
}
AppRegistry.registerComponent('MyNewAppreactold', () => MyNewAppreactold);
The code you shared doesn't authenticate the user. Since your security rules require that the user is authenticated to be allowed access to the data, they reject the unauthenticated user of your app.
To solve this problem, you'll need to authenticate the user. The simplest way to do that is to sign the user in anonymously:
firebase.auth().signInAnonymously();
Then attach your database listeners after the user is authenticated:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.listenForItems(this.itemsRef);
} else {
// User is signed out.
// ...
}
// ...
});

Yii2 - input search with auto-complete

I am using default Yii2 library for auto-complete. How can I make it, so it is reading values from DB while user is typing?
This is code I have so far, but query is done when the page is created:
echo AutoComplete::widget([
'name' => 'tradeName',
'model' => TradeNames::find()->select('name')->all(),
'options' => [
'class' => 'form-control'
],
'clientOptions' => [
'source' => array_column(TradeNames::find()->select('name')->asArray()->all(), 'name'),
},
],
]);
I followed this advice
jqueryui.com/autocomplete/#multiple and have written next code
<div id="autocomplete" class="ui-widget">
<?= \yii\jui\AutoComplete::widget([
'attribute' => 'attribute',
'name' => 'tradeName',
'clientOptions' => [
'source' => \Yii::$container->get('JsExpression',['function(request, response) {
response( $.ui.autocomplete.filter( window.dataAsArray, extractLast( request.term ) ) );
}']),
'select' => \Yii::$container->get('JsExpression',['function(event, ui) {
var terms = split( this.value );
terms.pop();
terms.push( ui.item.value );
terms.push( "" );
this.value = terms.join( ", " );
return false;
}']),
'focus' => \Yii::$container->get('JsExpression',['function() {
return false;
}']),
]
]) ?>
</div>
<script>
window.dataAsArray = ['item1', 'item2', 'item3'];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$(document).ready( function() {
$('#autocomplete').on('keydown', function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
});
});
</script>
maybe it help to someone
try this
use yii\jui\AutoComplete;
use yii\web\JsExpression;
<?php
$data = TradeNames::find()
->select(['name as value', 'name as label','id as id'])
->asArray()
->all();
echo 'Trade Names' .'<br>';
echo AutoComplete::widget([
'name' => 'tradeName',
'id' => 'trade_name',
'clientOptions' => [
'source' => $data,
// 'minLength'=>'3',
'autoFill'=>true,
'select' => new JsExpression("function( event, ui ) {
$('#memberssearch-family_name_id').val(ui.item.id);//#memberssearch-family_name_id is the id of hiddenInput.
}")],
]);
?>
<?= Html::activeHiddenInput($model, 'tradeName')?>

Resources