diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-05-08 17:10:06 +0200 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-11 23:55:58 +0200 |
commit | 8ff62c5f34db48aa15c7252c40fea3381bba0952 (patch) | |
tree | 2a0ffd9bcf9a2648c45f170426cf86fb319509f2 | |
parent | 1d2b34e71a01d6af118ed89258ad0ecb983e1a9c (diff) | |
parent | 59b8b2e26a7fff6072c4d5d96f51035dc900e0bc (diff) | |
download | cgeo-8ff62c5f34db48aa15c7252c40fea3381bba0952.zip cgeo-8ff62c5f34db48aa15c7252c40fea3381bba0952.tar.gz cgeo-8ff62c5f34db48aa15c7252c40fea3381bba0952.tar.bz2 |
merge upstream
982 files changed, 28917 insertions, 17108 deletions
@@ -2,19 +2,20 @@ bin/ gen/ annotation_gen/ +generated/ # vm crash logs hs_err_pid*.log +# annotation processor log files +androidannotations.log + # developer specific settings and credentials local.properties private.properties /crowdin/credentials /main/res/values/mapsapikey.xml -# eclipse plugin settings which cannot be shared -org.moreunit.prefs - /main/project/localization/*.missing /main/project/attributes/drawable-mdpi/ /main/project/attributes/iconlist1res.html diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..09a6d59 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +cgeo
\ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index 7cd87fc..c84cc54 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -5,6 +5,7 @@ <value> <option name="GENERATE_FINAL_LOCALS" value="true" /> <option name="GENERATE_FINAL_PARAMETERS" value="true" /> + <option name="USE_EXTERNAL_ANNOTATIONS" value="true" /> <option name="INSERT_INNER_CLASS_IMPORTS" value="true" /> <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50" /> <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50" /> @@ -38,9 +39,16 @@ <emptyLine /> </value> </option> + <option name="JD_KEEP_INVALID_TAGS" value="false" /> <option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" /> + <option name="JD_KEEP_EMPTY_PARAMETER" value="false" /> + <option name="JD_KEEP_EMPTY_EXCEPTION" value="false" /> + <option name="JD_KEEP_EMPTY_RETURN" value="false" /> <option name="JD_PARAM_DESCRIPTION_ON_NEW_LINE" value="true" /> <option name="WRAP_COMMENTS" value="true" /> + <JavaCodeStyleSettings> + <option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" /> + </JavaCodeStyleSettings> <XML> <option name="XML_KEEP_LINE_BREAKS" value="false" /> <option name="XML_ALIGN_ATTRIBUTES" value="false" /> @@ -54,6 +62,11 @@ <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" /> <option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" /> + <option name="IF_BRACE_FORCE" value="3" /> + <option name="DOWHILE_BRACE_FORCE" value="3" /> + <option name="WHILE_BRACE_FORCE" value="3" /> + <option name="FOR_BRACE_FORCE" value="3" /> + <option name="FIELD_ANNOTATION_WRAP" value="1" /> </codeStyleSettings> <codeStyleSettings language="XML"> <indentOptions> @@ -64,5 +77,4 @@ </option> <option name="USE_PER_PROJECT_SETTINGS" value="true" /> </component> -</project> - +</project>
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index f6e673a..e97777d 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,3 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> -<project version="4" /> +<project version="4"> + <component name="GradleSettings"> + <option name="linkedExternalProjectsSettings"> + <GradleProjectSettings> + <option name="distributionType" value="LOCAL" /> + <option name="externalProjectPath" value="$PROJECT_DIR$/google-play-services_lib" /> + <option name="gradleHome" value="/usr/share/java/gradle" /> + <option name="modules"> + <set> + <option value="$PROJECT_DIR$/google-play-services_lib" /> + </set> + </option> + </GradleProjectSettings> + </option> + </component> +</project> diff --git a/.idea/inspectionProfiles/c_geo_standards.xml b/.idea/inspectionProfiles/c_geo_standards.xml index cf3d2fb..8936fb5 100644 --- a/.idea/inspectionProfiles/c_geo_standards.xml +++ b/.idea/inspectionProfiles/c_geo_standards.xml @@ -2,6 +2,10 @@ <profile version="1.0" is_locked="false"> <option name="myName" value="c:geo standards" /> <option name="myLocal" value="false" /> + <inspection_tool class="AbstractMethodOverridesAbstractMethod" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoreJavaDoc" value="true" /> + <option name="ignoreAnnotations" value="true" /> + </inspection_tool> <inspection_tool class="AccessStaticViaInstance" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="AndroidLintBackButton" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="AndroidLintContentDescription" enabled="false" level="WARNING" enabled_by_default="false" /> @@ -14,67 +18,127 @@ <inspection_tool class="AndroidLintTooManyViews" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="AndroidLintUnusedResources" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="AndroidLintUsesMinSdkAttributes" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="AndroidLintWrongViewCast" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="Annotator" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="AntMissingPropertiesFileInspection" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="AntResolveInspection" enabled="false" level="ERROR" enabled_by_default="false" /> + <inspection_tool class="ArrayEquality" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ArraysAsListWithZeroOrOneArgument" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="AssignmentToCatchBlockParameter" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="AssignmentToMethodParameter" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreTransformationOfOriginalParameter" value="false" /> </inspection_tool> <inspection_tool class="AssignmentUsedAsCondition" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="BooleanMethodIsAlwaysInverted" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="BooleanMethodNameMustStartWithQuestion" enabled="false" level="TYPO" enabled_by_default="false"> + <option name="ignoreBooleanMethods" value="false" /> + <option name="ignoreInAnnotationInterface" value="true" /> + <option name="onlyWarnOnBaseMethods" value="true" /> + <option name="questionString" value="is,can,has,should,could,will,shall,check,contains,equals,add,put,remove,startsWith,endsWith,on,require" /> + </inspection_tool> + <inspection_tool class="BusyWait" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="CStyleArrayDeclaration" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="CanBeFinal" enabled="false" level="WARNING" enabled_by_default="false"> + <inspection_tool class="CanBeFinal" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="Changed Files" level="ERROR" enabled="true"> + <option name="REPORT_CLASSES" value="false" /> + <option name="REPORT_METHODS" value="false" /> + <option name="REPORT_FIELDS" value="true" /> + </scope> <option name="REPORT_CLASSES" value="false" /> <option name="REPORT_METHODS" value="false" /> <option name="REPORT_FIELDS" value="true" /> </inspection_tool> + <inspection_tool class="CastConflictsWithInstanceof" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="CastToIncompatibleInterface" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ChainedEquality" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="CheckEmptyScriptTag" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="CheckValidXmlInScriptTagBody" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="ClassInTopLevelPackage" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ClassNameDiffersFromFileName" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[A-Z][A-Za-z\d]*" /> + <option name="m_minLength" value="3" /> + <option name="m_maxLength" value="64" /> + </inspection_tool> + <inspection_tool class="ClassNewInstance" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ClassOnlyUsedInOneModule" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ClassOnlyUsedInOnePackage" enabled="false" level="WEAK WARNING" enabled_by_default="false" /> + <inspection_tool class="CollectionAddedToSelf" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="CollectionsFieldAccessReplaceableByMethodCall" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ComparableImplementedButEqualsNotOverridden" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ConditionSignal" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ConditionalExpressionWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ConfusingElse" enabled="true" level="WARNING" enabled_by_default="true"> <option name="reportWhenNoStatementFollow" value="false" /> </inspection_tool> - <inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true"> + <inspection_tool class="ConstantAssertCondition" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ConstantConditions" enabled="true" level="ERROR" enabled_by_default="true"> <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" /> <option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="true" /> </inspection_tool> + <inspection_tool class="ConstantNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="onlyCheckImmutables" value="false" /> + <option name="m_regex" value="[A-Z][A-Z_\d]*" /> + <option name="m_minLength" value="3" /> + <option name="m_maxLength" value="32" /> + </inspection_tool> + <inspection_tool class="ConstantStringIntern" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="CovariantCompareTo" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="CovariantEquals" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="CyclomaticComplexity" enabled="false" level="WEAK WARNING" enabled_by_default="false"> + <option name="m_limit" value="10" /> + </inspection_tool> <inspection_tool class="DefaultNotLastCaseInSwitch" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="Deprecation" enabled="true" level="WARNING" enabled_by_default="true"> <option name="IGNORE_INSIDE_DEPRECATED" value="true" /> </inspection_tool> + <inspection_tool class="DollarSignInName" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="DoubleLiteralMayBeFloatLiteral" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="DuplicateBooleanBranch" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="DuplicateCondition" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreMethodCalls" value="false" /> </inspection_tool> + <inspection_tool class="DynamicRegexReplaceableByCompiledPattern" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="EmptyCatchBlock" enabled="false" level="WARNING" enabled_by_default="false"> <option name="m_includeComments" value="true" /> <option name="m_ignoreTestCases" value="true" /> <option name="m_ignoreIgnoreParameter" value="true" /> </inspection_tool> <inspection_tool class="EmptyMethod" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="EmptySynchronizedStatement" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="EnumSwitchStatementWhichMissesCases" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreSwitchStatementsWithDefault" value="true" /> </inspection_tool> <inspection_tool class="EqualsAndHashcode" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ErrorRethrown" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="ExtendsThread" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="FallthruInSwitchStatement" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="FieldAccessedSynchronizedAndUnsynchronized" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="countGettersAndSetters" value="false" /> + </inspection_tool> <inspection_tool class="FieldCanBeLocal" enabled="true" level="ERROR" enabled_by_default="true" /> - <inspection_tool class="FieldMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="FinalStaticMethod" enabled="false" level="WARNING" enabled_by_default="false" /> - <inspection_tool class="ForCanBeForeach" enabled="false" level="WARNING" enabled_by_default="false"> - <option name="REPORT_INDEXED_LOOP" value="true" /> - <option name="ignoreUntypedCollections" value="false" /> + <inspection_tool class="FieldHidesSuperclassField" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_ignoreInvisibleFields" value="true" /> + </inspection_tool> + <inspection_tool class="FieldMayBeFinal" enabled="true" level="INFO" enabled_by_default="false"> + <scope name="cgeo project sources" level="ERROR" enabled="true" /> </inspection_tool> + <inspection_tool class="FieldMayBeStatic" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="FinalPrivateMethod" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="Changed Files" level="ERROR" enabled="true" /> + </inspection_tool> + <inspection_tool class="FinalStaticMethod" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="ForLoopReplaceableByWhile" enabled="true" level="WARNING" enabled_by_default="true"> <option name="m_ignoreLoopsWithoutConditions" value="false" /> </inspection_tool> + <inspection_tool class="ForLoopThatDoesntUseLoopVariable" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ForLoopWithMissingComponent" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreCollectionLoops" value="false" /> </inspection_tool> + <inspection_tool class="GrMethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="Changed Files" level="ERROR" enabled="true" /> + </inspection_tool> <inspection_tool class="GroovyDoubleCheckedLocking" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreOnVolatileVariables" value="true" /> </inspection_tool> @@ -108,8 +172,60 @@ </inspection_tool> <inspection_tool class="InfiniteLoopStatement" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="InnerClassMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="InstanceMethodNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_minLength" value="3" /> + <option name="m_maxLength" value="64" /> + </inspection_tool> + <inspection_tool class="InstanceVariableNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_minLength" value="2" /> + <option name="m_maxLength" value="30" /> + </inspection_tool> + <inspection_tool class="InstanceofCatchParameter" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="InstanceofIncompatibleInterface" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="InstanceofThis" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="JavaDoc" enabled="false" level="WARNING" enabled_by_default="false"> + <inspection_tool class="InstantiationOfUtilityClass" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="IntLiteralMayBeLongLiteral" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="InterfaceNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="m_regex" value="[A-Z][A-Za-z\d]*" /> + <option name="m_minLength" value="3" /> + <option name="m_maxLength" value="64" /> + </inspection_tool> + <inspection_tool class="IteratorHasNextCallsIteratorNext" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="IteratorNextDoesNotThrowNoSuchElementException" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="cgeo project sources" level="ERROR" enabled="true"> + <option name="TOP_LEVEL_CLASS_OPTIONS"> + <value> + <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> + <option name="REQUIRED_TAGS" value="" /> + </value> + </option> + <option name="INNER_CLASS_OPTIONS"> + <value> + <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> + <option name="REQUIRED_TAGS" value="" /> + </value> + </option> + <option name="METHOD_OPTIONS"> + <value> + <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> + <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" /> + </value> + </option> + <option name="FIELD_OPTIONS"> + <value> + <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> + <option name="REQUIRED_TAGS" value="" /> + </value> + </option> + <option name="IGNORE_DEPRECATED" value="false" /> + <option name="IGNORE_JAVADOC_PERIOD" value="true" /> + <option name="IGNORE_DUPLICATED_THROWS" value="false" /> + <option name="IGNORE_POINT_TO_ITSELF" value="false" /> + <option name="myAdditionalJavadocTags" value="" /> + </scope> <option name="TOP_LEVEL_CLASS_OPTIONS"> <value> <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> @@ -140,11 +256,31 @@ <option name="IGNORE_POINT_TO_ITSELF" value="false" /> <option name="myAdditionalJavadocTags" value="" /> </inspection_tool> - <inspection_tool class="JavadocReference" enabled="false" level="ERROR" enabled_by_default="false" /> + <inspection_tool class="KeySetIterationMayUseEntrySet" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="LengthOneStringInIndexOf" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ListIndexOfReplaceableByContains" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ListenerMayUseAdapter" enabled="true" level="WARNING" enabled_by_default="true"> <option name="checkForEmptyMethods" value="true" /> </inspection_tool> + <inspection_tool class="LocalCanBeFinal" enabled="true" level="INFO" enabled_by_default="false"> + <scope name="cgeo project sources" level="ERROR" enabled="true"> + <option name="REPORT_VARIABLES" value="true" /> + <option name="REPORT_PARAMETERS" value="true" /> + </scope> + <option name="REPORT_VARIABLES" value="true" /> + <option name="REPORT_PARAMETERS" value="true" /> + </inspection_tool> + <inspection_tool class="LocalVariableHidingMemberVariable" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_ignoreInvisibleFields" value="true" /> + <option name="m_ignoreStaticMethods" value="true" /> + </inspection_tool> + <inspection_tool class="LocalVariableNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="m_ignoreForLoopParameters" value="true" /> + <option name="m_ignoreCatchParameters" value="true" /> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_minLength" value="2" /> + <option name="m_maxLength" value="30" /> + </inspection_tool> <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false"> <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" /> <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" /> @@ -153,10 +289,26 @@ <option name="ignoreIterators" value="false" /> </inspection_tool> <inspection_tool class="LoopWithImplicitTerminationCondition" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MapReplaceableByEnumMap" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MethodCanBeVariableArityMethod" enabled="false" level="WARNING" enabled_by_default="false"> + <option name="ignoreByteAndShortArrayParameters" value="true" /> + <option name="ignoreOverridingMethods" value="true" /> + </inspection_tool> + <inspection_tool class="MethodCoupling" enabled="false" level="WEAK WARNING" enabled_by_default="false"> + <option name="m_includeJavaClasses" value="false" /> + <option name="m_includeLibraryClasses" value="false" /> + <option name="m_limit" value="10" /> + </inspection_tool> <inspection_tool class="MethodMayBeStatic" enabled="true" level="ERROR" enabled_by_default="true"> <option name="m_onlyPrivateOrFinal" value="false" /> <option name="m_ignoreEmptyMethods" value="true" /> </inspection_tool> + <inspection_tool class="MethodMayBeSynchronized" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MethodNamesDifferOnlyByCase" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="MethodOverloadsParentMethod" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MethodOverridesPackageLocalMethod" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MethodOverridesPrivateMethod" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MethodOverridesStaticMethod" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="MismatchedCollectionQueryUpdate" enabled="false" level="WARNING" enabled_by_default="false"> <option name="queryNames"> <value /> @@ -165,15 +317,42 @@ <value /> </option> </inspection_tool> + <inspection_tool class="MissingDeprecatedAnnotation" enabled="true" level="ERROR" enabled_by_default="true" /> <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreObjectMethods" value="true" /> <option name="ignoreAnonymousClassMethods" value="false" /> </inspection_tool> + <inspection_tool class="MisspelledCompareTo" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MisspelledEquals" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MisspelledHashcode" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="MisspelledToString" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NakedNotify" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NegatedIfElse" enabled="false" level="WARNING" enabled_by_default="false"> <option name="m_ignoreNegatedNullComparison" value="true" /> <option name="m_ignoreNegatedZeroComparison" value="true" /> </inspection_tool> - <inspection_tool class="NonFinalFieldInEnum" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NestedSynchronizedStatement" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NestingDepth" enabled="false" level="WEAK WARNING" enabled_by_default="false"> + <option name="m_limit" value="5" /> + </inspection_tool> + <inspection_tool class="NonAtomicOperationOnVolatileField" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NonBooleanMethodNameMayNotStartWithQuestion" enabled="true" level="TYPO" enabled_by_default="true"> + <option name="questionString" value="is,can,has,should,could,will,shall,contains,equals,startsWith,endsWith" /> + <option name="ignoreBooleanMethods" value="false" /> + <option name="onlyWarnOnBaseMethods" value="true" /> + </inspection_tool> + <inspection_tool class="NonCommentSourceStatements" enabled="false" level="WEAK WARNING" enabled_by_default="false"> + <option name="m_limit" value="30" /> + </inspection_tool> + <inspection_tool class="NonExceptionNameEndsWithException" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NonFinalFieldInEnum" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="Changed Files" level="ERROR" enabled="true" /> + </inspection_tool> + <inspection_tool class="NonShortCircuitBoolean" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NonSynchronizedMethodOverridesSynchronizedMethod" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NotifyCalledOnCondition" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NotifyNotInSynchronizedContext" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="NotifyWithoutCorrespondingWait" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NullableProblems" enabled="true" level="ERROR" enabled_by_default="true"> <option name="REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL" value="true" /> <option name="REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL" value="true" /> @@ -184,20 +363,55 @@ <option name="REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS" value="true" /> <option name="REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD" value="true" /> </inspection_tool> - <inspection_tool class="ObjectEquality" enabled="true" level="WARNING" enabled_by_default="true"> - <option name="m_ignoreEnums" value="true" /> - <option name="m_ignoreClassObjects" value="false" /> - <option name="m_ignorePrivateConstructors" value="false" /> - </inspection_tool> + <inspection_tool class="ObjectNotify" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ObjectToString" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ObsoleteCollection" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreRequiredObsoleteCollectionTypes" value="false" /> </inspection_tool> + <inspection_tool class="OverloadedMethodsWithSameNumberOfParameters" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoreInconvertibleTypes" value="true" /> + </inspection_tool> + <inspection_tool class="PackageNamingConvention" enabled="true" level="TYPO" enabled_by_default="true"> + <option name="m_regex" value="[a-z]*" /> + <option name="m_minLength" value="2" /> + <option name="m_maxLength" value="16" /> + </inspection_tool> + <inspection_tool class="ParameterCanBeLocal" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="Changed Files" level="ERROR" enabled="true" /> + </inspection_tool> + <inspection_tool class="ParameterHidingMemberVariable" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_ignoreInvisibleFields" value="true" /> + <option name="m_ignoreStaticMethodParametersHidingInstanceFields" value="true" /> + <option name="m_ignoreForConstructors" value="true" /> + <option name="m_ignoreForPropertySetters" value="true" /> + <option name="m_ignoreForAbstractMethods" value="false" /> + </inspection_tool> + <inspection_tool class="ParameterNameDiffersFromOverriddenParameter" enabled="false" level="WEAK WARNING" enabled_by_default="false"> + <option name="m_ignoreSingleCharacterNames" value="false" /> + <option name="m_ignoreOverridesOfLibraryMethods" value="false" /> + </inspection_tool> + <inspection_tool class="ParameterNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_minLength" value="1" /> + <option name="m_maxLength" value="30" /> + </inspection_tool> <inspection_tool class="PointlessArithmeticExpression" enabled="false" level="WARNING" enabled_by_default="false"> <option name="m_ignoreExpressionsContainingConstants" value="false" /> </inspection_tool> <inspection_tool class="PointlessIndexOfComparison" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="PointlessNullCheck" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="ProtectedMemberInFinalClass" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ProtectedMemberInFinalClass" enabled="true" level="WARNING" enabled_by_default="true"> + <scope name="Changed Files" level="ERROR" enabled="true" /> + </inspection_tool> + <inspection_tool class="PublicFieldAccessedInSynchronizedContext" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="QuestionableName" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="nameString" value="aa,abc,bad,bar,bar2,baz,baz1,baz2,baz3,bb,blah,bogus,bool,cc,dd,defau1t,dummy,dummy2,ee,fa1se,ff,foo,foo1,foo2,foo3,foobar,four,fred,fred1,fred2,gg,hh,hello,hello1,hello2,hello3,ii,nu11,one,silly,silly2,string,two,that,then,three,whi1e,var" /> + </inspection_tool> + <inspection_tool class="RandomDoubleForRandomInteger" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="RedundantArrayCreation" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="RedundantStringFormatCall" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="RedundantSuppression" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="ReplaceAllDot" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ReplaceAssignmentWithOperatorAssignment" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreLazyOperators" value="true" /> <option name="ignoreObscureOperators" value="false" /> @@ -205,6 +419,7 @@ <inspection_tool class="RequiredAttributes" enabled="false" level="WARNING" enabled_by_default="false"> <option name="myAdditionalRequiredHtmlAttributes" value="" /> </inspection_tool> + <inspection_tool class="ResourceType" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ReturnFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="ReturnNull" enabled="false" level="WEAK WARNING" enabled_by_default="false"> <option name="m_reportObjectMethods" value="true" /> @@ -212,40 +427,88 @@ <option name="m_reportCollectionMethods" value="true" /> <option name="m_ignorePrivateMethods" value="false" /> </inspection_tool> + <inspection_tool class="SafeLock" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SameParameterValue" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="SameReturnValue" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="SharedThreadLocalRandom" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="SignalWithoutCorrespondingAwait" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SimplifiableEqualsExpression" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SimplifiableIfStatement" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="Since15" enabled="true" level="ERROR" enabled_by_default="true"> + <effectiveLL value="JDK_1_6" /> + </inspection_tool> <inspection_tool class="SizeReplaceableByIsEmpty" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="SleepWhileHoldingLock" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> <option name="processCode" value="true" /> <option name="processLiterals" value="true" /> <option name="processComments" value="true" /> </inspection_tool> + <inspection_tool class="StaticCallOnSubclass" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="StaticFieldReferenceOnSubclass" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="StaticMethodNamingConvention" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_minLength" value="1" /> + <option name="m_maxLength" value="64" /> + </inspection_tool> + <inspection_tool class="StaticVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false"> + <option name="checkMutableFinals" value="false" /> + <option name="m_regex" value="[a-z][A-Za-z\d]*" /> + <option name="m_minLength" value="3" /> + <option name="m_maxLength" value="30" /> + </inspection_tool> <inspection_tool class="StringBufferReplaceableByString" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="StringBufferToStringInConcatenation" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="StringConcatenationInFormatCall" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="StringConcatenationInMessageFormatCall" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="StringConcatenationMissingWhitespace" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoreNonStringLiterals" value="true" /> + </inspection_tool> <inspection_tool class="StringConstructor" enabled="false" level="WARNING" enabled_by_default="false"> <option name="ignoreSubstringArguments" value="false" /> </inspection_tool> - <inspection_tool class="SuspiciousMethodCalls" enabled="false" level="WARNING" enabled_by_default="false"> - <option name="REPORT_CONVERTIBLE_METHOD_CALLS" value="true" /> + <inspection_tool class="StringEqualsEmptyString" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="StringReplaceableByStringBuffer" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="onlyWarnOnLoop" value="true" /> </inspection_tool> + <inspection_tool class="SubstringZero" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SwitchStatementWithConfusingDeclaration" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SwitchStatementWithTooFewBranches" enabled="true" level="WARNING" enabled_by_default="true"> <option name="m_limit" value="2" /> </inspection_tool> - <inspection_tool class="SynchronizationOnLocalVariableOrMethodParameter" enabled="false" level="WARNING" enabled_by_default="false"> - <option name="reportLocalVariables" value="true" /> - <option name="reportMethodParameters" value="true" /> - </inspection_tool> + <inspection_tool class="SynchronizeOnLock" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="SynchronizedOnLiteralObject" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="SyntaxError" enabled="false" level="ERROR" enabled_by_default="false" /> + <inspection_tool class="SystemGC" enabled="true" level="ERROR" enabled_by_default="true" /> <inspection_tool class="SystemOutErr" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="SystemRunFinalizersOnExit" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="TextLabelInSwitchStatement" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadDeathRethrown" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="ThreadLocalNotStaticFinal" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadPriority" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadRun" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadStartInConstruction" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadStopSuspendResume" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadWithDefaultRunMethod" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreadYield" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="ThreeNegationsPerMethod" enabled="false" level="WEAK WARNING" enabled_by_default="false"> + <option name="m_ignoreInEquals" value="true" /> + <option name="ignoreInAssert" value="false" /> + </inspection_tool> <inspection_tool class="TooBroadScope" enabled="true" level="WARNING" enabled_by_default="true"> <option name="m_allowConstructorAsInitializer" value="false" /> <option name="m_onlyLookAtBlocks" value="false" /> </inspection_tool> + <inspection_tool class="TrivialStringConcatenation" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="TryFinallyCanBeTryWithResources" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="TypeParameterNamingConvention" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_regex" value="[A-Z][A-Za-z\d]*" /> + <option name="m_minLength" value="1" /> + <option name="m_maxLength" value="16" /> + </inspection_tool> <inspection_tool class="UNCHECKED_WARNING" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="UnaryPlus" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="UnconditionalWait" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessarilyQualifiedStaticallyImportedElement" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessaryBlockStatement" enabled="true" level="WARNING" enabled_by_default="true"> <option name="ignoreSwitchBranches" value="true" /> @@ -253,15 +516,27 @@ <inspection_tool class="UnnecessaryCallToStringValueOf" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessaryConstructor" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessaryEnumModifier" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WEAK WARNING" enabled_by_default="true"> + <option name="m_ignoreJavadoc" value="false" /> + </inspection_tool> + <inspection_tool class="UnnecessaryInheritDoc" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="UnnecessaryJavaDocLink" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoreInlineLinkToSuper" value="false" /> + </inspection_tool> <inspection_tool class="UnnecessaryModuleDependencyInspection" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnnecessaryQualifierForThis" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnnecessarySuperConstructor" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="UnnecessaryUnaryMinus" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnusedAssignment" enabled="true" level="WARNING" enabled_by_default="true"> <option name="REPORT_PREFIX_EXPRESSIONS" value="false" /> <option name="REPORT_POSTFIX_EXPRESSIONS" value="false" /> <option name="REPORT_REDUNDANT_INITIALIZER" value="true" /> </inspection_tool> + <inspection_tool class="UnusedCatchParameter" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="m_ignoreCatchBlocksWithComments" value="false" /> + <option name="m_ignoreTestCases" value="false" /> + </inspection_tool> <inspection_tool class="UnusedDeclaration" enabled="false" level="WARNING" enabled_by_default="false"> <option name="ADD_MAINS_TO_ENTRIES" value="true" /> <option name="ADD_APPLET_TO_ENTRIES" value="true" /> @@ -272,14 +547,26 @@ <inspection_tool class="UnusedParameters" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnusedProperty" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnusedReturnValue" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="UpperCaseFieldNameNotConstant" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="UseOfPropertiesAsHashtable" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UtilityClassWithPublicConstructor" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="WaitCalledOnCondition" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="WaitNotInLoop" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="WaitNotInSynchronizedContext" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="WaitOrAwaitWithoutTimeout" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="WaitWhileHoldingTwoLocks" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="WaitWithoutCorrespondingNotify" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="WeakerAccess" enabled="false" level="WARNING" enabled_by_default="false"> <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" /> <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" /> <option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" /> </inspection_tool> + <inspection_tool class="WhileLoopSpinsOnField" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoreNonEmtpyLoops" value="false" /> + </inspection_tool> <inspection_tool class="XmlDuplicatedId" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="XmlHighlighting" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="XmlUnboundNsPrefix" enabled="false" level="WARNING" enabled_by_default="false" /> + <inspection_tool class="ZeroLengthArrayInitialization" enabled="true" level="WARNING" enabled_by_default="true" /> </profile> </component>
\ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 3ee65a0..1c2e7a0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,6 +3,24 @@ <component name="EntryPointsManager"> <entry_points version="2.0" /> </component> + <component name="JavadocGenerationManager"> + <option name="OUTPUT_DIRECTORY" value="/tmp/javadoc" /> + <option name="OPTION_SCOPE" value="package" /> + <option name="OPTION_HIERARCHY" value="true" /> + <option name="OPTION_NAVIGATOR" value="true" /> + <option name="OPTION_INDEX" value="true" /> + <option name="OPTION_SEPARATE_INDEX" value="true" /> + <option name="OPTION_DOCUMENT_TAG_USE" value="false" /> + <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" /> + <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" /> + <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" /> + <option name="OPTION_DEPRECATED_LIST" value="true" /> + <option name="OTHER_OPTIONS" /> + <option name="HEAP_SIZE" /> + <option name="LOCALE" /> + <option name="OPEN_IN_BROWSER" value="true" /> + <option name="OPTION_INCLUDE_LIBS" value="true" /> + </component> <component name="NullableNotNullManager"> <option name="myDefaultNullable" value="org.eclipse.jdt.annotation.Nullable" /> <option name="myDefaultNotNull" value="org.eclipse.jdt.annotation.NonNull" /> @@ -30,8 +48,7 @@ <component name="ProjectResources"> <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="Android 4.4.2 Google APIs" project-jdk-type="Android SDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="Android 5.0 Google APIs" project-jdk-type="Android SDK"> <output url="file://$PROJECT_DIR$/out" /> </component> -</project> - +</project>
\ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index e58c500..8efb78b 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -7,6 +7,8 @@ <module fileurl="file://$PROJECT_DIR$/cgeo-calendar/cgeo-calendar.iml" filepath="$PROJECT_DIR$/cgeo-calendar/cgeo-calendar.iml" /> <module fileurl="file://$PROJECT_DIR$/cgeo-contacts/cgeo-contacts.iml" filepath="$PROJECT_DIR$/cgeo-contacts/cgeo-contacts.iml" /> <module fileurl="file://$PROJECT_DIR$/mapswithme-api/mapswithme-api.iml" filepath="$PROJECT_DIR$/mapswithme-api/mapswithme-api.iml" /> + <module fileurl="file://$PROJECT_DIR$/play-services-base/play-services-base.iml" filepath="$PROJECT_DIR$/play-services-base/play-services-base.iml" /> + <module fileurl="file://$PROJECT_DIR$/play-services-location/play-services-location.iml" filepath="$PROJECT_DIR$/play-services-location/play-services-location.iml" /> <module fileurl="file://$PROJECT_DIR$/showcaseview/showcaseview.iml" filepath="$PROJECT_DIR$/showcaseview/showcaseview.iml" /> <module fileurl="file://$PROJECT_DIR$/tests/tests.iml" filepath="$PROJECT_DIR$/tests/tests.iml" /> </modules> diff --git a/.idea/scopes/cgeo_project_sources.xml b/.idea/scopes/cgeo_project_sources.xml new file mode 100644 index 0000000..f53ea95 --- /dev/null +++ b/.idea/scopes/cgeo_project_sources.xml @@ -0,0 +1,3 @@ +<component name="DependencyValidationManager"> + <scope name="cgeo project sources" pattern="src[cgeo]:cgeo.calendar..*||src[cgeo]:cgeo.contacts..*||src[cgeo]:cgeo.geocaching..*||file[cgeo]:res//*||file[cgeo]:AndroidManifest.xml" /> +</component>
\ No newline at end of file @@ -1,14 +1,17 @@ [c:geo](http://www.cgeo.org) is an open source, full-featured, always ready-to-go client for geocaching.com (unofficial) and offers basic support for other geocaching platforms. It does not require a web browser or exports - just download and start right away. -You want to contribute? ------------------------ +## You want to contribute? + Perfect! Please **tell us in the [issue tracker](https://github.com/cgeo/cgeo/issues) before hacking** on your great new feature. It would be bad if you have implemented something great, but we can't include it because it doesn't fit the remaining architecture and code. You might also want to chat with the developers on channel #cgeo on the freenode IRC network. -[![Build Status](http://ci.cgeo.org/job/c-geo/badge/icon)](http://ci.cgeo.org/job/c-geo/) +## Project status + +[![Build Status](http://ci.cgeo.org/job/c-geo/badge/icon)](http://ci.cgeo.org/job/c-geo/)<br> +[![Issue Stats](http://issuestats.com/github/cgeo/cgeo/badge/pr)](http://issuestats.com/github/cgeo/cgeo)<br> +[![Issue Stats](http://issuestats.com/github/cgeo/cgeo/badge/issue)](http://issuestats.com/github/cgeo/cgeo) -Get the source --------------- +## Get the source Fork the [project source code](https://github.com/cgeo/cgeo), make changes to your clone and [create a pull request](https://help.github.com/articles/using-pull-requests) afterwards. @@ -20,20 +23,18 @@ Fork the [project source code](https://github.com/cgeo/cgeo), make changes to yo A more complex bugfix can be first tested against the `master` branch and integrated in the nightly builds, while kept compatible with the `release` branch for a later integration. Such a procedure is [described in the wiki](https://github.com/cgeo/cgeo/wiki/How-to-get-a-bug-fix-into-the-release). -Set up Eclipse --------------- +## Set up Eclipse - Install an Eclipse distribution for your OS from http://eclipse.org/downloads/ (you may choose the Java developers distribution). - Start Eclipse, choose any directory as workspace. Close the welcome screen, if it appears. - After the workbench has started, select File | Import | Install | Install Software Items From File and select a locally downloaded copy of https://github.com/cgeo/cgeo/tree/master/main/project/eclipse%20installation/cgeo%20eclipse%20components.p2f. This way you can easily install all necessary plugins. - After forking the project you should import the Eclipse projects in your workspace with File | Import | Projects from Git. -Build ------ +## Build ### Prerequisites ### -- [Android SDK](http://developer.android.com/sdk) (latest version) including Google APIs V19 (although we target API 7) +- [Android SDK](http://developer.android.com/sdk) (latest version) including Google APIs V19 - [Ant](http://ant.apache.org) 1.6.0+ for building c:geo on the command line (not necessary when using only Eclipse) - If you use Microsoft Windows, [Google USB Driver](http://developer.android.com/sdk/win-usb.html) to install the application on the smartphone @@ -52,11 +53,18 @@ If the workspace directory name contains a space and leads to errors in the -dex 3. copy `./main/templates/local.properties` to `./main/` 4. copy `./main/templates/local.properties` to `./tests/` 5. edit `local.properties` (see comments in the file) +6. copy `local.properties` to all other projects (currently android-support-v7-appcompat, google-play-services_lib, mapswithme-api, showcaseview) +7. copy `local.properties` to cgeo-calender and cgeo-contatcs if you plan to hack on the plugins 6. copy `./main/templates/keys.xml` to `./main/res/values/` 7. edit `./main/res/values/keys.xml` and insert several keys (see comments in the file) - * Google Maps API key (you can leave it empty, but then Google Maps don't work) - * request your personal consumer key and secret at [opencaching.de OKAPI signup](http://www.opencaching.de/okapi/signup.html) - * request your personal consumer key and secret at [opencaching.pl OKAPI signup](http://www.opencaching.pl/okapi/signup.html) + * Google Maps API v1 key (you can leave it empty, but then Google Maps don't work - Google doesn't hand out new keys for Google Maps v1, you have to use an existing one) + * request your personal consumer key and secret for the various opencaching nodes we support: + * [opencaching.de OKAPI signup](http://www.opencaching.de/okapi/signup.html) + * [opencaching.pl OKAPI signup](http://www.opencaching.pl/okapi/signup.html) + * [opencaching.ro OKAPI signup](http://www.opencaching.ro/okapi/signup.html) + * [opencaching.nl OKAPI signup](http://www.opencaching.nl/okapi/signup.html) + * [opencaching.us OKAPI signup](http://www.opencaching.us/okapi/signup.html) + * [opencaching.org.uk OKAPI signup](http://www.opencaching.org.uk/okapi/signup.html) ### Building with Ant ### @@ -82,13 +90,11 @@ To run all tests use the same "Run As" menu item from the context menu of the te For tests to run successfully you need to configure c:geo on the emulator that runs the test with a valid geocaching.com account. In order for all tests to be successfull the account needs to be premium. -License -------- +## License c:geo is distributed under [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). -Contact -------- +## Contact - Website: http://www.cgeo.org/ - Support: support@cgeo.org @@ -97,3 +103,4 @@ Contact - Google+: https://plus.google.com/105588163414303246956 - Google Play: https://play.google.com/store/apps/details?id=cgeo.geocaching - Live status: http://status.cgeo.org/ +- Developer chat: [#cgeo on freenode.net](https://webchat.freenode.net/?channels=%23cgeo) diff --git a/android-support-v7-appcompat/android-support-v7-appcompat.iml b/android-support-v7-appcompat/android-support-v7-appcompat.iml index 35b1b99..2d81b27 100644 --- a/android-support-v7-appcompat/android-support-v7-appcompat.iml +++ b/android-support-v7-appcompat/android-support-v7-appcompat.iml @@ -15,6 +15,7 @@ <facet type="android" name="Android"> <configuration> <option name="LIBRARY_PROJECT" value="true" /> + <option name="UPDATE_PROPERTY_FILES" value="false" /> </configuration> </facet> </component> @@ -46,5 +47,203 @@ </orderEntry> <orderEntry type="sourceFolder" forTests="false" /> </component> -</module> - + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/android-support-v7-appcompat/lint.xml b/android-support-v7-appcompat/lint.xml index 9fffd8d..a41ed72 100644 --- a/android-support-v7-appcompat/lint.xml +++ b/android-support-v7-appcompat/lint.xml @@ -1,14 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?> <lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> <issue id="AllowBackup" severity="ignore" /> <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> <issue id="ButtonCase" severity="ignore" /> <issue id="ButtonOrder" severity="ignore" /> <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> <issue id="CommitPrefEdits" severity="ignore" /> <issue id="CommitTransaction" severity="ignore" /> <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> <issue id="CutPasteId" severity="ignore" /> <issue id="DalvikOverride" severity="ignore" /> <issue id="DefaultLocale" severity="ignore" /> @@ -23,13 +33,22 @@ <issue id="DuplicateUsesFeature" severity="ignore" /> <issue id="EnforceUTF8" severity="ignore" /> <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> <issue id="ExportedReceiver" severity="ignore" /> <issue id="ExportedService" severity="ignore" /> <issue id="ExtraText" severity="ignore" /> <issue id="ExtraTranslation" severity="ignore" /> <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> <issue id="GrantAllUris" severity="ignore" /> <issue id="GridLayout" severity="ignore" /> <issue id="HandlerLeak" severity="ignore" /> @@ -48,10 +67,14 @@ <issue id="IconNoDpi" severity="ignore" /> <issue id="IconXmlAndPng" severity="ignore" /> <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="ImproperProjectLevelStatement" severity="ignore" /> <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> <issue id="InconsistentArrays" severity="ignore" /> <issue id="InconsistentLayout" severity="ignore" /> <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> <issue id="InlinedApi" severity="ignore" /> <issue id="InnerclassSeparator" severity="ignore" /> <issue id="Instantiatable" severity="ignore" /> @@ -61,11 +84,13 @@ <issue id="LabelFor" severity="ignore" /> <issue id="LibraryCustomView" severity="ignore" /> <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> <issue id="MangledCRLF" severity="ignore" /> <issue id="ManifestOrder" severity="ignore" /> <issue id="ManifestTypo" severity="ignore" /> <issue id="MenuTitle" severity="ignore" /> <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MisplacedStatement" severity="ignore" /> <issue id="MissingApplicationIcon" severity="ignore" /> <issue id="MissingId" severity="ignore" /> <issue id="MissingPrefix" severity="ignore" /> @@ -80,6 +105,7 @@ <issue id="NestedScrolling" severity="ignore" /> <issue id="NestedWeights" severity="ignore" /> <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> <issue id="NotSibling" severity="ignore" /> <issue id="ObsoleteLayoutParam" severity="ignore" /> <issue id="OldTargetApi" severity="ignore" /> @@ -92,13 +118,21 @@ <issue id="PrivateResource" severity="ignore" /> <issue id="Proguard" severity="ignore" /> <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> <issue id="ProtectedPermissions" severity="ignore" /> <issue id="PxUsage" severity="ignore" /> <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> <issue id="Registered" severity="ignore" /> <issue id="RequiredSize" severity="ignore" /> <issue id="ResAuto" severity="ignore" /> <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> <issue id="ScrollViewCount" severity="ignore" /> <issue id="ScrollViewSize" severity="ignore" /> <issue id="SdCardPath" severity="ignore" /> @@ -106,6 +140,7 @@ <issue id="ServiceCast" severity="ignore" /> <issue id="SetJavaScriptEnabled" severity="ignore" /> <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> <issue id="SimpleDateFormat" severity="ignore" /> <issue id="SmallSp" severity="ignore" /> <issue id="SpUsage" severity="ignore" /> @@ -113,6 +148,7 @@ <issue id="StringFormatCount" severity="ignore" /> <issue id="StringFormatInvalid" severity="ignore" /> <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> <issue id="StyleCycle" severity="ignore" /> <issue id="Suspicious0dp" severity="ignore" /> <issue id="SuspiciousImport" severity="ignore" /> @@ -130,6 +166,7 @@ <issue id="UnknownId" severity="ignore" /> <issue id="UnknownIdInLayout" severity="ignore" /> <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> <issue id="UnusedNamespace" severity="ignore" /> <issue id="UnusedQuantity" severity="ignore" /> <issue id="UnusedResources" severity="ignore" /> @@ -142,8 +179,10 @@ <issue id="UsesMinSdkAttributes" severity="ignore" /> <issue id="ValidFragment" severity="ignore" /> <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> <issue id="ViewTag" severity="ignore" /> <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> <issue id="WorldReadableFiles" severity="ignore" /> <issue id="WorldWriteableFiles" severity="ignore" /> <issue id="WrongCall" severity="ignore" /> diff --git a/cgeo-calendar/.classpath b/cgeo-calendar/.classpath index 2f1c26a..004d749 100644 --- a/cgeo-calendar/.classpath +++ b/cgeo-calendar/.classpath @@ -10,5 +10,6 @@ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry combineaccessrules="false" kind="src" path="/cgeo"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> + <classpathentry kind="lib" path="/cgeo/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs b/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs index 6ae8f9e..4ef7c1f 100644 --- a/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs +++ b/cgeo-calendar/.settings/org.eclipse.jdt.core.prefs @@ -13,6 +13,7 @@ org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore @@ -36,12 +37,25 @@ org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning diff --git a/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs b/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs index 7616a5b..06e562c 100644 --- a/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs +++ b/cgeo-calendar/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,3 @@ -#Wed Sep 14 20:41:07 CEST 2011 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_cgeo @@ -9,7 +8,7 @@ org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -20,15 +19,17 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false +sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true @@ -36,15 +37,16 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -52,10 +54,13 @@ sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/cgeo-calendar/AndroidManifest.xml b/cgeo-calendar/AndroidManifest.xml index 64968e5..0a406d3 100644 --- a/cgeo-calendar/AndroidManifest.xml +++ b/cgeo-calendar/AndroidManifest.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cgeo.calendar" - android:versionCode="4" - android:versionName="1.4" > + android:versionCode="5" + android:versionName="1.5" > <uses-sdk android:minSdkVersion="7" diff --git a/cgeo-calendar/build.gradle b/cgeo-calendar/build.gradle index 6b36270..4663e5f 100644 --- a/cgeo-calendar/build.gradle +++ b/cgeo-calendar/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 19 - buildToolsVersion "19.1.0" + buildToolsVersion "21.1.2" @@ -26,4 +26,4 @@ android { dependencies { // The dependency to the ICalnder interface from the main project is missing // compile project(":main") is not working -}
\ No newline at end of file +} diff --git a/cgeo-calendar/cgeo-calendar.iml b/cgeo-calendar/cgeo-calendar.iml index f0b6226..da62bdf 100644 --- a/cgeo-calendar/cgeo-calendar.iml +++ b/cgeo-calendar/cgeo-calendar.iml @@ -6,6 +6,7 @@ <proGuardCfgFiles> <file>file://$MODULE_DIR$/proguard-project.txt</file> </proGuardCfgFiles> + <option name="UPDATE_PROPERTY_FILES" value="false" /> <includeAssetsFromLibraries>true</includeAssetsFromLibraries> </configuration> </facet> @@ -29,5 +30,203 @@ </library> </orderEntry> </component> -</module> - + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/cgeo-calendar/proguard-project.txt b/cgeo-calendar/proguard-project.txt index 453d1a6..c4cb930 100644 --- a/cgeo-calendar/proguard-project.txt +++ b/cgeo-calendar/proguard-project.txt @@ -29,4 +29,7 @@ public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); public void set*(...); -}
\ No newline at end of file +} + +# Null analysis annotations of Eclipse JDT are just used by the Eclipse compiler, so ignore them here +-dontwarn org.eclipse.jdt.annotation.** diff --git a/cgeo-calendar/res/values-es/strings.xml b/cgeo-calendar/res/values-es/strings.xml index 172c6e0..6838aa3 100644 --- a/cgeo-calendar/res/values-es/strings.xml +++ b/cgeo-calendar/res/values-es/strings.xml @@ -3,6 +3,6 @@ <resources> <string name="app_name">c:geo - calendario (complemento)</string> <string name="calendars">Calendarios</string> - <string name="event_success">Escondite/Evento añadido al calendario</string> - <string name="event_fail">Error al añadir escondite/evento al calendario</string> + <string name="event_success">Evento añadido al calendario</string> + <string name="event_fail">Error al añadir el evento al calendario</string> </resources> diff --git a/cgeo-calendar/res/values-lv/strings.xml b/cgeo-calendar/res/values-lv/strings.xml new file mode 100644 index 0000000..b11c6cd --- /dev/null +++ b/cgeo-calendar/res/values-lv/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="app_name">c:geo - kalendÄrs (Add-on)</string> + <string name="calendars">KalendÄri</string> + <string name="event_success">PasÄkuma slÄ“pnis pievienots kalendÄram</string> + <string name="event_fail">NeizdevÄs pievienot kalendÄram PasÄkuma slÄ“pni</string> +</resources> diff --git a/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java b/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java index 31e2bd9..e35ed19 100644 --- a/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/AbstractAddEntry.java @@ -1,13 +1,17 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.util.Log; abstract class AbstractAddEntry { - protected CalendarEntry entry; - protected CalendarActivity activity; + @NonNull + protected final CalendarEntry entry; + @NonNull + protected final CalendarActivity activity; - public AbstractAddEntry(final CalendarEntry entry, CalendarActivity activity) { + public AbstractAddEntry(@NonNull final CalendarEntry entry, @NonNull final CalendarActivity activity) { this.entry = entry; this.activity = activity; } @@ -16,7 +20,7 @@ abstract class AbstractAddEntry { try { addEntryToCalendarInternal(); activity.showToast(R.string.event_success); - } catch (Exception e) { + } catch (final Exception e) { activity.showToast(R.string.event_fail); Log.e(CalendarActivity.LOG_TAG, "addToCalendar", e); diff --git a/cgeo-calendar/src/cgeo/calendar/AddEntry.java b/cgeo-calendar/src/cgeo/calendar/AddEntry.java index cdb59d9..a267e47 100644 --- a/cgeo-calendar/src/cgeo/calendar/AddEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/AddEntry.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.content.ContentValues; import android.net.Uri; import android.text.Html; @@ -8,14 +10,15 @@ import java.util.Date; class AddEntry extends AbstractAddEntry { - private int calendarId; + private final int calendarId; /** * @param entry + * new entry to be stored * @param calendarId - * The selected calendar + * The selected calendar */ - public AddEntry(CalendarEntry entry, CalendarActivity activity, int calendarId) { + public AddEntry(@NonNull final CalendarEntry entry, @NonNull final CalendarActivity activity, final int calendarId) { super(entry, activity); this.calendarId = calendarId; } diff --git a/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java b/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java index 0ceed67..731a0f8 100644 --- a/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java +++ b/cgeo-calendar/src/cgeo/calendar/AddEntryLevel14.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.content.Intent; import android.text.Html; @@ -12,7 +14,7 @@ import java.util.Date; */ class AddEntryLevel14 extends AbstractAddEntry { - public AddEntryLevel14(CalendarEntry entry, CalendarActivity activity) { + public AddEntryLevel14(@NonNull final CalendarEntry entry, @NonNull final CalendarActivity activity) { super(entry, activity); } diff --git a/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java b/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java index 2fbfd05..e21de2b 100644 --- a/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java +++ b/cgeo-calendar/src/cgeo/calendar/CalendarActivity.java @@ -1,5 +1,7 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; @@ -16,7 +18,7 @@ public final class CalendarActivity extends Activity { /** Called when the activity is first created. */ @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { @@ -35,7 +37,7 @@ public final class CalendarActivity extends Activity { } else { selectCalendarForAdding(entry); } - } catch (Exception e) { + } catch (final Exception e) { Log.e(LOG_TAG, e.getMessage(), e); finish(); } @@ -45,40 +47,10 @@ public final class CalendarActivity extends Activity { * Adds the cache to the Android-calendar if it is an event. * * @param entry + * new entry to be stored */ - private void selectCalendarForAdding(final CalendarEntry entry) { - final String[] projection = new String[] { "_id", "displayName" }; - final Uri calendarProvider = Compatibility.getCalendarProviderURI(); - - final Cursor cursor = managedQuery(calendarProvider, projection, "selected=1", null, null); - - if (cursor == null || cursor.getCount() <= 0) { - showToast(R.string.event_fail); - finish(); - return; - } - - final SparseArray<String> calendars = new SparseArray<>(); - cursor.moveToFirst(); - - final int indexId = cursor.getColumnIndex("_id"); - final int indexName = cursor.getColumnIndex("displayName"); - - do { - final String idString = cursor.getString(indexId); - if (idString != null) { - try { - int id = Integer.parseInt(idString); - final String calName = cursor.getString(indexName); - - if (id > 0 && calName != null) { - calendars.put(id, calName); - } - } catch (NumberFormatException e) { - Log.e(LOG_TAG, "CalendarActivity.selectCalendarForAdding", e); - } - } - } while (cursor.moveToNext()); + private void selectCalendarForAdding(@NonNull final CalendarEntry entry) { + final SparseArray<String> calendars = queryCalendars(); if (calendars.size() == 0) { showToast(R.string.event_fail); @@ -95,7 +67,7 @@ public final class CalendarActivity extends Activity { builder.setTitle(R.string.calendars); builder.setItems(items, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int item) { + public void onClick(final DialogInterface dialog, final int item) { final int calendarId = calendars.keyAt(item); new AddEntry(entry, CalendarActivity.this, calendarId).addEntryToCalendar(); finish(); @@ -103,13 +75,56 @@ public final class CalendarActivity extends Activity { }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override - public void onCancel(DialogInterface dialog) { + public void onCancel(final DialogInterface dialog) { finish(); } }); builder.create().show(); } + @NonNull + private SparseArray<String> queryCalendars() { + final SparseArray<String> calendars = new SparseArray<>(); + + final Uri calendarProvider = Compatibility.getCalendarProviderURI(); + + Cursor cursor = null; + try { + final String[] projection = new String[]{"_id", "displayName"}; + cursor = getContentResolver().query(calendarProvider, projection, "selected=1", null, null); + + if (cursor == null) { + return calendars; + } + + cursor.moveToFirst(); + + final int indexId = cursor.getColumnIndex("_id"); + final int indexName = cursor.getColumnIndex("displayName"); + + do { + final String idString = cursor.getString(indexId); + if (idString != null) { + try { + final int id = Integer.parseInt(idString); + final String calName = cursor.getString(indexName); + + if (id > 0 && calName != null) { + calendars.put(id, calName); + } + } catch (final NumberFormatException e) { + Log.e(LOG_TAG, "CalendarActivity.selectCalendarForAdding", e); + } + } + } while (cursor.moveToNext()); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return calendars; + } + public final void showToast(final int res) { final String text = getResources().getString(res); final Toast toast = Toast.makeText(this, text, Toast.LENGTH_LONG); diff --git a/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java b/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java index a1761c7..8308b7b 100644 --- a/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java +++ b/cgeo-calendar/src/cgeo/calendar/CalendarEntry.java @@ -3,6 +3,7 @@ package cgeo.calendar; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.CharEncoding; +import org.eclipse.jdt.annotation.NonNull; import android.net.Uri; import android.text.Html; @@ -16,16 +17,23 @@ import java.util.Date; class CalendarEntry { - private String shortDesc; - private String hiddenDate; - private String url; - private String personalNote; - private String name; - private String coords; + @NonNull + private final String shortDesc; + @NonNull + private final String hiddenDate; + @NonNull + private final String url; + @NonNull + private final String personalNote; + @NonNull + private final String name; + @NonNull + private final String coords; private int startTimeMinutes = -1; - private Uri uri; + @NonNull + private final Uri uri; - public CalendarEntry(final Uri uri) { + public CalendarEntry(@NonNull final Uri uri) { this.uri = uri; this.shortDesc = getParameter(ICalendar.PARAM_SHORT_DESC); this.hiddenDate = getParameter(ICalendar.PARAM_HIDDEN_DATE); @@ -37,20 +45,21 @@ class CalendarEntry { if (startTime.length() > 0) { try { this.startTimeMinutes = Integer.parseInt(startTime); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { Log.e("CalendarEntry creation", e); } } } - private String getParameter(final String paramKey) { + @NonNull + private String getParameter(@NonNull final String paramKey) { try { final String param = uri.getQueryParameter(paramKey); if (param == null) { return ""; } return URLDecoder.decode(param, CharEncoding.UTF_8).trim(); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { Log.e("CalendarEntry.getParameter", e); } return ""; @@ -60,18 +69,22 @@ class CalendarEntry { return getName().length() > 0 && getHiddenDate().length() > 0; } + @NonNull public String getHiddenDate() { return hiddenDate; } + @NonNull public String getUrl() { return url; } + @NonNull public String getPersonalNote() { return personalNote; } + @NonNull public String getShortDesc() { return shortDesc; } @@ -79,24 +92,26 @@ class CalendarEntry { /** * @return <code>Date</code> based on hidden date. Time is set to 00:00:00. */ + @NonNull protected Date parseDate() { try { - Calendar cal = Calendar.getInstance(); + final Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(Long.parseLong(getHiddenDate())); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); return cal.getTime(); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { // cannot happen normally, but static code analysis does not know + throw new IllegalStateException("hidden date must be a valid date for cache calendar entries"); } - return null; } /** * @return description string with images removed and personal note included */ + @NonNull protected String parseDescription() { final StringBuilder description = new StringBuilder(); description.append(getUrl()); @@ -121,6 +136,7 @@ class CalendarEntry { return description.toString(); } + @NonNull public String getName() { return name; } @@ -129,6 +145,7 @@ class CalendarEntry { return startTimeMinutes; } + @NonNull public String getCoords() { return coords; } diff --git a/cgeo-calendar/src/cgeo/calendar/Compatibility.java b/cgeo-calendar/src/cgeo/calendar/Compatibility.java index 8813f41..61ea636 100644 --- a/cgeo-calendar/src/cgeo/calendar/Compatibility.java +++ b/cgeo-calendar/src/cgeo/calendar/Compatibility.java @@ -1,23 +1,27 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + import android.net.Uri; import android.os.Build; public final class Compatibility { - private final static int sdkVersion = Build.VERSION.SDK_INT; - private final static boolean isLevel8 = sdkVersion >= 8; - private final static boolean isLevel14 = sdkVersion >= 14; + private final static int SDK_VERSION = Build.VERSION.SDK_INT; + private final static boolean IS_LEVEL_8 = SDK_VERSION >= 8; + private final static boolean IS_LEVEL_14 = SDK_VERSION >= 14; + @NonNull public static Uri getCalendarProviderURI() { - return Uri.parse(isLevel8 ? "content://com.android.calendar/calendars" : "content://calendar/calendars"); + return Uri.parse(IS_LEVEL_8 ? "content://com.android.calendar/calendars" : "content://calendar/calendars"); } + @NonNull public static Uri getCalendarEventsProviderURI() { - return Uri.parse(isLevel8 ? "content://com.android.calendar/events" : "content://calendar/events"); + return Uri.parse(IS_LEVEL_8 ? "content://com.android.calendar/events" : "content://calendar/events"); } public static boolean isLevel14() { - return isLevel14; + return IS_LEVEL_14; } } diff --git a/cgeo-contacts/.classpath b/cgeo-contacts/.classpath index 448b12e..004d749 100644 --- a/cgeo-contacts/.classpath +++ b/cgeo-contacts/.classpath @@ -10,6 +10,6 @@ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry combineaccessrules="false" kind="src" path="/cgeo"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> - <classpathentry kind="lib" path="org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar"/> + <classpathentry kind="lib" path="/cgeo/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/cgeo-contacts/.settings/org.eclipse.jdt.core.prefs b/cgeo-contacts/.settings/org.eclipse.jdt.core.prefs index 90a6f5b..f8876c8 100644 --- a/cgeo-contacts/.settings/org.eclipse.jdt.core.prefs +++ b/cgeo-contacts/.settings/org.eclipse.jdt.core.prefs @@ -13,6 +13,7 @@ org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore @@ -36,12 +37,25 @@ org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning diff --git a/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs b/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs index 7616a5b..06e562c 100644 --- a/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs +++ b/cgeo-contacts/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,3 @@ -#Wed Sep 14 20:41:07 CEST 2011 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_cgeo @@ -9,7 +8,7 @@ org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -20,15 +19,17 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false +sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true @@ -36,15 +37,16 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -52,10 +54,13 @@ sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/cgeo-contacts/AndroidManifest.xml b/cgeo-contacts/AndroidManifest.xml index f441973..b7ef1c5 100644 --- a/cgeo-contacts/AndroidManifest.xml +++ b/cgeo-contacts/AndroidManifest.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cgeo.contacts" - android:versionCode="3" - android:versionName="1.3" > + android:versionCode="5" + android:versionName="1.5" > <uses-sdk android:minSdkVersion="7" diff --git a/cgeo-contacts/build.gradle b/cgeo-contacts/build.gradle index e35cff8..74d135b 100644 --- a/cgeo-contacts/build.gradle +++ b/cgeo-contacts/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 19 - buildToolsVersion "19.1.0" + buildToolsVersion "21.1.2" @@ -28,4 +28,4 @@ dependencies { compile files('../main/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar') // The depency to the ICalnder interface from the main project is missing // compile(:main) is not right -}
\ No newline at end of file +} diff --git a/cgeo-contacts/cgeo-contacts.iml b/cgeo-contacts/cgeo-contacts.iml index c045b7e..1b85002 100644 --- a/cgeo-contacts/cgeo-contacts.iml +++ b/cgeo-contacts/cgeo-contacts.iml @@ -15,6 +15,7 @@ <proGuardCfgFiles> <file>file://$MODULE_DIR$/proguard-project.txt</file> </proGuardCfgFiles> + <option name="UPDATE_PROPERTY_FILES" value="false" /> </configuration> </facet> </component> @@ -28,5 +29,203 @@ <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="cgeo" /> </component> -</module> - + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/cgeo-contacts/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar b/cgeo-contacts/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar Binary files differdeleted file mode 100644 index daca164..0000000 --- a/cgeo-contacts/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar +++ /dev/null diff --git a/cgeo-contacts/res/values-lv/strings.xml b/cgeo-contacts/res/values-lv/strings.xml new file mode 100644 index 0000000..3da741e --- /dev/null +++ b/cgeo-contacts/res/values-lv/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="app_name">c:geo - kontakti (Add-on)</string> + <string name="contact_not_found">Kontakts ar pseidonÄ«mu/niku %s nav atrasts. Vispirms pievienojiet kontaktpersonas aplikÄcijai.</string> + <string name="multiple_matches">VairÄkas atbilstÄ«bas</string> +</resources> diff --git a/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java b/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java index bbda493..74b2617 100644 --- a/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java +++ b/cgeo-contacts/src/cgeo/contacts/ContactsActivity.java @@ -7,6 +7,7 @@ import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.database.Cursor; @@ -28,7 +29,7 @@ public final class ContactsActivity extends Activity { static final String LOG_TAG = "cgeo.contacts"; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Uri uri = getIntent().getData(); @@ -67,14 +68,14 @@ public final class ContactsActivity extends Activity { selectContact(contacts); } else { - int contactId = contacts.get(0).first; + final int contactId = contacts.get(0).first; openContactAndFinish(contactId); } } - private void selectContact(final List<Pair<Integer, String>> contacts) { - List<String> list = new ArrayList<>(); - for (Pair<Integer, String> p : contacts) { + private void selectContact(@NonNull final List<Pair<Integer, String>> contacts) { + final List<String> list = new ArrayList<>(); + for (final Pair<Integer, String> p : contacts) { list.add(p.second); } final CharSequence[] items = list.toArray(new CharSequence[list.size()]); @@ -82,38 +83,48 @@ public final class ContactsActivity extends Activity { .setTitle(R.string.multiple_matches) .setItems(items, new OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - int contactId = contacts.get(which).first; + @Override + public void onClick(final DialogInterface dialog, final int which) { + final int contactId = contacts.get(which).first; dialog.dismiss(); openContactAndFinish(contactId); } }) + .setOnCancelListener(new OnCancelListener() { + + @Override + public void onCancel(final DialogInterface dialog) { + dialog.dismiss(); + finish(); + } + }) .create().show(); } - private void openContactAndFinish(int id) { + private void openContactAndFinish(final int id) { final Intent intent = new Intent(Intent.ACTION_VIEW); - Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(id)); + final Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(id)); intent.setData(uri); startActivity(intent); finish(); } - private List<Pair<Integer, String>> getContacts(final @NonNull String searchName, Uri uri, final @NonNull String idColumnName, final @NonNull String selectionColumnName, boolean like) { + @NonNull + private List<Pair<Integer, String>> getContacts(final @NonNull String searchName, final Uri uri, final @NonNull String idColumnName, final @NonNull String selectionColumnName, final boolean like) { final String[] projection = new String[] { idColumnName, selectionColumnName }; final String selection = selectionColumnName + (like ? " LIKE" : " =") + " ? COLLATE NOCASE"; final String[] selectionArgs = new String[] { like ? "%" + searchName + "%" : searchName }; Cursor cursor = null; - List<Pair<Integer, String>> result = new ArrayList<>(); + final List<Pair<Integer, String>> result = new ArrayList<>(); try { cursor = getContentResolver().query(uri, projection, selection, selectionArgs, null); while (cursor != null && cursor.moveToNext()) { - int foundId = cursor.getInt(0); - String foundName = cursor.getString(1); + final int foundId = cursor.getInt(0); + final String foundName = cursor.getString(1); result.add(new Pair<>(foundId, foundName)); } - } catch (Exception e) { + } catch (final Exception e) { Log.e(LOG_TAG, "ContactsActivity.getContactId", e); } finally { if (cursor != null) { @@ -130,14 +141,15 @@ public final class ContactsActivity extends Activity { toast.show(); } - private static String getParameter(final Uri uri, final String paramKey) { + @NonNull + private static String getParameter(@NonNull final Uri uri, @NonNull final String paramKey) { try { final String param = uri.getQueryParameter(paramKey); if (param == null) { return StringUtils.EMPTY; } return URLDecoder.decode(param, CharEncoding.UTF_8).trim(); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { Log.e(LOG_TAG, "ContactsActivity.getParameter", e); } return StringUtils.EMPTY; diff --git a/crowdin/download b/crowdin/download index 7465ad3..b6bbe40 100755 --- a/crowdin/download +++ b/crowdin/download @@ -10,12 +10,12 @@ # see: http://crowdin.net/page/api/export # see: http://crowdin.net/page/api/download -. "`dirname $0`/globals" +. "$(dirname $0)/globals" BRANCH=crowdin_translations GITHUB_PR_TITLE="crowdin: New translations" PR_EXISTS=0 -DDATE=`date +"%Y-%m-%d %H:%M:%S"` +DDATE=$(date +"%Y-%m-%d %H:%M:%S") ZIPFILE=all.zip # default base branch BASE_BRANCH=master @@ -76,10 +76,10 @@ for f in */*/*values-*/strings.xml; do done # apply local patches to particular strings -. "`dirname $0`/local-patches" +. "$progdir/local-patches" # check for changes -if [ -z "`git diff`" ]; then +if [ -z "$(git diff)" ]; then debug "no changes, finishing." finish exit @@ -87,7 +87,7 @@ fi # upload changes to github AMEND="" -[[ ! -z "`git log ${BASE_BRANCH}..${BRANCH}`" ]] && AMEND="--amend" +[[ ! -z "$(git log ${BASE_BRANCH}..${BRANCH})" ]] && AMEND="--amend" _do git commit -a "${AMEND}" -m \"${GITHUB_PR_TITLE}\" || die "commit failed." _do git push -f origin "${BRANCH}" || die "git push failed." diff --git a/crowdin/globals b/crowdin/globals index dc2e9c9..80f7e83 100755 --- a/crowdin/globals +++ b/crowdin/globals @@ -1,8 +1,10 @@ #!/bin/bash -. "`dirname $0`/credentials" +progdir=$(cd $(dirname "$0") && pwd) -OUT=/tmp/crowdin.`basename $0`.`date +%Y-%m-%d.%H:%M:%S`.out +. "$progdir/credentials" + +OUT=/tmp/crowdin.$(basename $0).$(date +%Y-%m-%d.%H:%M:%S).out crowdin_surf () { _do curl -o "${OUT}" $@ || die "curl produced an error." @@ -15,7 +17,7 @@ require_tools () { # code taken from backup2l local NOT_AVAIL="" for TOOL in $@; do - if [ "`which $TOOL 2> /dev/null`" == "" ]; then NOT_AVAIL="$NOT_AVAIL $TOOL"; fi + if [ "$(which $TOOL 2> /dev/null)" == "" ]; then NOT_AVAIL="$NOT_AVAIL $TOOL"; fi done if [[ "$NOT_AVAIL" != "" ]]; then die "The following required tool(s) cannot be found: $NOT_AVAIL" @@ -32,7 +34,7 @@ map_to_crowdin_code () { finish () { : ; } die () { for i; do debug "$i"; done; finish; exit 1; } -debug () { echo "`date +%Y-%m-%d.%H:%M:%S` `basename $0`: $@"; } +debug () { echo $(date +%Y-%m-%d.%H:%M:%S) $(basename $0): $@; } # use this function for executing commands. _do () { debug "$@"; eval "$@"; } @@ -40,5 +42,4 @@ _do () { debug "$@"; eval "$@"; } require_tools git curl wget unzip sed git rev-parse --show-toplevel >& /dev/null || die "Please start this script from within a repo. Aborting." -cd "`git rev-parse --show-toplevel`" - +cd "$(git rev-parse --show-toplevel)" diff --git a/crowdin/update b/crowdin/update index 984b62f..757e948 100755 --- a/crowdin/update +++ b/crowdin/update @@ -18,7 +18,7 @@ update_file() { "http://api.crowdin.net/api/project/cgeo/update-file?key=${CROWDIN_APIKEY}" } -. "`dirname $0`/globals" +. "$(dirname $0)/globals" echo You must be on an up-to-date master branch to execute this script. echo You have 5 seconds to abort with ctrl-c if this is not the case. diff --git a/crowdin/upload b/crowdin/upload index 547989e..b7010ea 100755 --- a/crowdin/upload +++ b/crowdin/upload @@ -15,7 +15,7 @@ # upload_file uploads the file in parameter 1 to the crowdin file name in parameter 2 upload_file() { if [ -f "$2" ]; then - CROWDIN_LANG=`map_to_crowdin_code "$1"` + CROWDIN_LANG=$(map_to_crowdin_code "$1") crowdin_surf \ -F \"files[$3]=@$2\" \ -F \"language=$CROWDIN_LANG\" \ @@ -26,7 +26,7 @@ upload_file() { fi } -. "`dirname $0`/globals" +. "$(dirname $0)/globals" if [ $# -eq 0 ]; then debug "no languages passed - aborting." diff --git a/main/.factorypath b/main/.factorypath index 1440abd..289e9ae 100644 --- a/main/.factorypath +++ b/main/.factorypath @@ -1,4 +1,4 @@ <factorypath> - <factorypathentry kind="WKSPJAR" id="/cgeo/libs/butterknife-5.1.1.jar" enabled="true" runInBatchMode="false"/> - <factorypathentry kind="WKSPJAR" id="/cgeo/compile-libs/androidannotations-3.0.1.jar" enabled="true" runInBatchMode="false"/> + <factorypathentry kind="WKSPJAR" id="/cgeo/libs/butterknife-6.1.0.jar" enabled="true" runInBatchMode="false"/> + <factorypathentry kind="WKSPJAR" id="/cgeo/compile-libs/androidannotations-3.2.jar" enabled="true" runInBatchMode="false"/> </factorypath> diff --git a/main/.settings/org.eclipse.jdt.core.prefs b/main/.settings/org.eclipse.jdt.core.prefs index 0de28b5..70c3ee6 100644 --- a/main/.settings/org.eclipse.jdt.core.prefs +++ b/main/.settings/org.eclipse.jdt.core.prefs @@ -49,9 +49,9 @@ org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore @@ -61,7 +61,7 @@ org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public -org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled diff --git a/main/.settings/org.eclipse.jdt.ui.prefs b/main/.settings/org.eclipse.jdt.ui.prefs index 4d4a905..4c0bdef 100644 --- a/main/.settings/org.eclipse.jdt.ui.prefs +++ b/main/.settings/org.eclipse.jdt.ui.prefs @@ -6,13 +6,15 @@ org.eclipse.jdt.ui.exception.name=e org.eclipse.jdt.ui.gettersetter.use.is=true org.eclipse.jdt.ui.ignorelowercasenames=true org.eclipse.jdt.ui.importorder=cgeo;com;org;android;java;javax; +org.eclipse.jdt.ui.javadoc=false org.eclipse.jdt.ui.keywordthis=false org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.overrideannotation=true org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * \n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates> sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -41,15 +43,15 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true diff --git a/main/.settings/org.moreunit.prefs b/main/.settings/org.moreunit.prefs new file mode 100644 index 0000000..17ff166 --- /dev/null +++ b/main/.settings/org.moreunit.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.moreunit.preferences.version=2 +org.moreunit.unitsourcefolder=cgeo\:src\:cgeo-test\:src\#cgeo\:src\:cgeo-test\:gen +org.moreunit.useprojectsettings=true diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index dfc1e43..372e4b9 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -7,7 +7,7 @@ <uses-sdk android:minSdkVersion="9" - android:targetSdkVersion="19" /> + android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> @@ -45,16 +45,34 @@ android:name="com.google.android.maps" android:required="false" /> + <!-- Samsung Multi-Window support --> + <uses-library + android:name="com.sec.android.app.multiwindow" + android:required="false" /> + + <meta-data + android:name="com.sec.android.support.multiwindow" + android:value="true" /> + <meta-data + android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" + android:resource="@dimen/app_defaultsize_w" /> + <meta-data + android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" + android:resource="@dimen/app_defaultsize_h" /> <meta-data android:name="android.app.default_searchable" android:value=".SearchActivity" /> <meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIsvD_aUSDMwWOf9NkwwxZ4kJJI_AG2EaxjSu2jw" /> + <meta-data + android:name="com.google.android.gms.version" + android:value="@integer/google_play_services_version" /> <activity android:name=".MainActivity" android:configChanges="keyboardHidden|orientation|screenSize" + android:exported="true" android:label="@string/app_name" android:theme="@style/cgeo_main" android:windowSoftInputMode="stateHidden" > @@ -68,14 +86,24 @@ <activity android:name=".SearchActivity" android:configChanges="keyboardHidden|orientation|screenSize" + android:exported="true" android:label="@string/app_name" android:launchMode="singleTop" android:parentActivityName="cgeo.geocaching.MainActivity" android:windowSoftInputMode="stateHidden" > + + <!-- keyword based search from search widget --> <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> - + + <!-- This can trigger our app from Google Now by something like "Search for keyword on c:geo". + See http://developer.android.com/guide/components/intents-common.html#Search --> + <intent-filter> + <action android:name="com.google.android.gms.actions.SEARCH_ACTION"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> + <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="cgeo.geocaching.MainActivity" /> @@ -136,6 +164,7 @@ <activity android:name=".NavigateAnyPointActivity" android:configChanges="keyboardHidden|orientation|screenSize" + android:exported="true" android:label="@string/search_destination" android:parentActivityName="cgeo.geocaching.MainActivity" android:windowSoftInputMode="stateHidden" > @@ -166,6 +195,7 @@ <activity android:name=".CacheListActivity" android:configChanges="keyboardHidden|orientation|screenSize" + android:exported="true" android:label="@string/app_name" android:parentActivityName="cgeo.geocaching.MainActivity" > <meta-data @@ -207,6 +237,11 @@ </intent-filter> </activity> <activity + android:exported="true" + android:name=".maps.MapActivity" + android:label="@string/map_map" > + </activity> + <activity android:name=".maps.google.v1.GoogleMapActivity" android:label="@string/map_map" > </activity> @@ -245,8 +280,37 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> + + <!-- extremcaching.com --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="extremcaching.com" + android:pathPrefix="/index.php/output-2/" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.extremcaching.com" + android:pathPrefix="/index.php/output-2/" + android:scheme="http" /> + </intent-filter> + + <!-- geocaching.com --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -258,6 +322,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -269,6 +334,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -280,6 +346,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -289,8 +356,49 @@ android:pathPrefix="/seek/cache_details.aspx" android:scheme="http" /> </intent-filter> + + <!-- opencaching.CZ --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.cz" + android:pathPrefix="/OZ" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.cz" + android:pathPrefix="/OZ" + android:scheme="http" /> + </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.cz" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.DE --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -302,6 +410,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -313,6 +422,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -322,7 +432,350 @@ android:pathPrefix="/viewcache.php" android:scheme="http" /> </intent-filter> + + <!-- opencaching.ES --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencachingspain.es" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencachingspain.es" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencachingspain.es" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.FR --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.fr" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.fr" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.fr" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.IT --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.it" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.it" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.it" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.NO --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.no" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.no" + android:pathPrefix="/OC" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.no" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.NL --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.nl" + android:pathPrefix="/OB" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.nl" + android:pathPrefix="/OB" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.nl" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.PL --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.pl" + android:pathPrefix="/OP" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.pl" + android:pathPrefix="/OP" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.pl" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.ORG.UK --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.org.uk" + android:pathPrefix="/OK" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.org.uk" + android:pathPrefix="/OK" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.org.uk" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.RO --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.ro" + android:pathPrefix="/OR" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.ro" + android:pathPrefix="/OR" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.ro" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> + + <!-- opencaching.US --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="opencaching.us" + android:pathPrefix="/OU" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.us" + android:pathPrefix="/OU" + android:scheme="http" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="www.opencaching.us" + android:pathPrefix="/viewcache.php" + android:scheme="http" /> + </intent-filter> </activity> + <activity android:name="cgeo.geocaching.TrackableActivity" android:configChanges="keyboardHidden|orientation|screenSize" @@ -331,6 +784,7 @@ <!-- TravelBug URL via coord.info redirection --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -342,6 +796,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -355,6 +810,7 @@ <!-- TravelBug URL tracking page --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -366,6 +822,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -376,9 +833,24 @@ android:scheme="http" /> </intent-filter> - <!-- GeoKrety URLs --> + <!-- geocaching.com.au swaggies --> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data + android:host="geocaching.com.au" + android:pathPrefix="/swaggie/sw" + android:scheme="http" /> + </intent-filter> + + <!-- GeoKrety.org --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -390,6 +862,7 @@ </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> @@ -400,31 +873,32 @@ android:scheme="http" /> </intent-filter> - <!-- - Geokrety QR code URLs, not yet implemented + <!-- GeoKretyMap.org --> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data - android:host="geokrety.org" - android:pathPrefix="/m/qr.php" + android:host="geokretymap.org" + android:pathPrefix="/" android:scheme="http" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> + <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data - android:host="www.geokrety.org" - android:pathPrefix="/m/qr.php" + android:host="www.geokretymap.org" + android:pathPrefix="/" android:scheme="http" /> </intent-filter> - --> + </activity> <activity android:name=".CompassActivity" @@ -501,9 +975,14 @@ </activity> + <activity + android:name=".filter.FilterActivity_" + android:label="@string/caches_filter_title" > + </activity> + <!-- provide enhanced meta data for caches (and waypoints) when invoking Locus from c:geo --> <provider - android:name=".apps.LocusDataStorageProvider" + android:name="menion.android.locus.LocusDataStorageProvider" android:authorities="cgeo.geocaching.apps.locusdatastorageprovider" /> <!-- search suggestions for the search bar at the top --> @@ -512,4 +991,4 @@ android:authorities="cgeo.geocaching.search.SuggestionProvider" /> </application> -</manifest>
\ No newline at end of file +</manifest> diff --git a/main/build.gradle b/main/build.gradle index e809018..06a36e8 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -26,15 +26,22 @@ gradle connectedCheck //Testing guide : http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing //https://github.com/stephanenicolas/Quality-Tools-for-Android -def AAVersion = '3.0.1' -def RXVersion = '0.19.6' +def AAVersion = '3.2' +def RXJavaVersion = '1.0.8' +def RXAndroidVersion = '0.24.0' +def JacksonCoreVersion = '2.5.1' +def JacksonDatabindVersion = '2.5.1' +def JacksonAnnotationsVersion = '2.5.1' +def CommonsCollections4Version = '4.0' +def CommonsLang3Version = '3.3.2' +def CommonsIoVersion = '2.4' group = 'cgeo.geocaching' version = '0.0.1' android { //compileSdkVersion "Google Inc.:Google APIs:19" compileSdkVersion 19 - buildToolsVersion "19.1.0" + buildToolsVersion "21.1.2" compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 @@ -61,9 +68,7 @@ android { // NOTE: must match the package in the test directory and must be different from the app package testApplicationId "cgeo.geocaching.test" - // standard android test runner - //testInstrumentationRunner "android.test.InstrumentationTestRunner" - testInstrumentationRunner "com.zutubi.android.junitreport.JUnitReportTestRunner" + testInstrumentationRunner "cgeo.junit.CgeoTestRunner" //testHandlingProfiling true testFunctionalTest true @@ -81,8 +86,8 @@ android { //packageNameSuffix ".debug" //zipAlign = true debuggable true - runProguard false - proguardFiles getDefaultProguardFile('proguard-android.txt'), '../tests/proguard.cfg' + runProguard true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' versionNameSuffix " Debug " + versionProps['betaNumber'] } release { @@ -152,19 +157,23 @@ dependencies { compile files('libs/mapsforge-map-0.3.0-jar-with-dependencies.jar') compile 'com.android.support:appcompat-v7:19.1.0' + compile 'com.google.android.gms:play-services:6.5.+' + + compile 'com.jakewharton:butterknife:6.1.0' + compile "org.apache.commons:commons-collections4:$CommonsCollections4Version" + compile "org.apache.commons:commons-lang3:$CommonsLang3Version" + compile "commons-io:commons-io:$CommonsIoVersion" + compile 'com.google.code.findbugs:annotations:3.0.0' - compile 'com.jakewharton:butterknife:5.1.1' - compile 'org.apache.commons:commons-collections4:4.0' - compile 'org.apache.commons:commons-lang3:3.3.2' - compile 'commons-io:commons-io:2.4' - compile 'com.google.code.findbugs:annotations:2.0.3' + compile "io.reactivex:rxjava:$RXJavaVersion" + compile "io.reactivex:rxandroid:$RXAndroidVersion" - compile "com.netflix.rxjava:rxjava-core:$RXVersion" - compile "com.netflix.rxjava:rxjava-android:$RXVersion" - compile "com.netflix.rxjava:rxjava-async-util:$RXVersion" + compile "com.fasterxml.jackson.core:jackson-core:$JacksonCoreVersion" + compile "com.fasterxml.jackson.core:jackson-databind:$JacksonDatabindVersion" + compile "com.fasterxml.jackson.core:jackson-annotations:$JacksonAnnotationsVersion" //TEST - //compile files('compile-libs/androidannotations-3.0.1.jar') + //compile files('compile-libs/androidannotations-3.2.jar') //compile files('compile-libs/findbugs-ant.jar') //compile files('compile-libs/findbugs-jsr305.jar') //CheckForNull conflict with com.google.code.findbugs:annotations compile files('compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar') @@ -202,7 +211,7 @@ apt { //http://www.gradle.org/docs/current/dsl/org.gradle.api.plugins.quality.FindBugsExtension.html findbugs { - toolVersion = "2.0.1" + toolVersion = "3.0.0" //sourceSets = [sourceSets.main] ignoreFailures = true reportsDir = file("$project.buildDir/reports") @@ -249,11 +258,11 @@ dependencies { unitTestCompile 'com.google.android:android-test:4.1.1.4' unitTestCompile 'com.googlecode.androidannotations:androidannotations-api:$AAVersion' - unitTestCompile 'com.jakewharton:butterknife:5.1.1' + unitTestCompile 'com.jakewharton:butterknife:6.1.0' unitTestCompile 'org.apache.commons:commons-collections4:4.0' unitTestCompile 'commons-io:commons-io:2.4' - unitTestCompile 'org.apache.commons:commons-lang3:3.3.2' - unitTestCompile 'com.google.code.findbugs:annotations:2.0.3' + unitTestCompile 'org.apache.commons:commons-lang3:$CommonsLang3Version' + unitTestCompile 'com.google.code.findbugs:annotations:3.0.0' unitTestCompile 'com.netflix.rxjava:rxjava-core:$RXVersion' unitTestCompile 'com.netflix.rxjava:rxjava-android:$RXVersion' } diff --git a/main/build.xml b/main/build.xml index 43c37b2..5eb7768 100644 --- a/main/build.xml +++ b/main/build.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <project name="cgeo"> - <!-- The local.properties file is created and updated by the 'android' tool. + <!-- The local.properties file is created and updated by the 'android' tool. It contains the path to the SDK. It should *NOT* be checked into Version Control Systems. --> - <loadproperties srcFile="local.properties" /> + <loadproperties srcFile="local.properties" /> - <!-- The ant.properties file can be created by you. It is only edited by the + <!-- The ant.properties file can be created by you. It is only edited by the 'android' tool to add properties to it. This is the place to change some Ant specific build properties. Here are some properties you may want to change/update: @@ -26,9 +26,9 @@ application and should be checked into Version Control Systems. --> - <property file="ant.properties" /> + <property file="ant.properties" /> - <!-- The project.properties file is created and updated by the 'android' + <!-- The project.properties file is created and updated by the 'android' tool, as well as ADT. This contains project specific properties such as project target, and library @@ -37,36 +37,48 @@ This file is an integral part of the build system for your application and should be checked into Version Control Systems. --> - <loadproperties srcFile="project.properties" /> - - <!-- The private.properties file sets api-keys as well as keystore, + <loadproperties srcFile="project.properties" /> + + <!-- The private.properties file sets api-keys as well as keystore, certificate and passwords (if you want). See /templates/private.properties for more information. --> - <property file="private.properties" /> + <property file="private.properties" /> - <!-- quick check on sdk.dir --> - <fail + <!-- quick check on sdk.dir --> + <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" /> - - <!-- Custom targets --> - <target name="install_release" description="Install signed release application" depends="release"> - <exec executable="${sdk.dir}/platform-tools/adb"> - <arg line="-d install -r ./bin/${ant.project.name}-release.apk" /> - </exec> - </target> - - <target name="debugAPI" depends="-pre-build" + + <!-- Custom targets --> + <target name="install_release" description="Install signed release application" depends="release"> + <exec executable="${sdk.dir}/platform-tools/adb"> + <arg line="-d install -r ./bin/${ant.project.name}-release.apk" /> + </exec> + </target> + + <target name="run_release" description="Run signed release application" depends="install_release"> + <exec executable="${sdk.dir}/platform-tools/adb"> + <arg line="-d shell am start -n cgeo.geocaching/.MainActivity" /> + </exec> + </target> + + <target name="debugAPI" depends="-pre-build" description="Changes API key to debug"> - </target> - + </target> + <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask"> <classpath> - <pathelement location="./compile-libs/findbugs-ant.jar"/> + <pathelement location="./compile-libs/findbugs-ant.jar"/> </classpath> </taskdef> + <!-- We need to enable ProGuard in debug mode as we otherwise run into the 64 K methods dex limit. + As long as we don't obfuscate, we can even use the same ProGuard config in both builds. --> + <target name="-debug-obfuscation-check"> + <property name="proguard.enabled" value="true"/> + </target> + <target name="findbugs"> <mkdir dir="reports" /> <gettarget @@ -81,67 +93,83 @@ outputFile="reports/findbugs.xml" excludefilter="project/findbugs/exclusions.xml" effort="max" - reportLevel="low"> + reportLevel="low" + jvmargs="-Xmx1024m"> <auxClasspath path="${project.target.android.jar}" /> <class location="${out.dir}" /> </findbugs> </target> - + <!-- extension targets. Uncomment the ones where you want to do custom work in between standard targets --> - <target name="-pre-build"> - <condition property="build.mode.release" else="false"> - <equals arg1="${build.target}" arg2="release" /> - </condition> - - <if condition="${build.mode.release}"> - <then> - <filterset id="maps-key"> - <filter token="maps.api.key" value="${maps.api.key.market}"/> - </filterset> - </then> - <else> - <filterset id="maps-key"> - <filter token="maps.api.key" value="${maps.api.key}"/> - </filterset> - </else> - </if> - <copy file="./templates/keys.xml" todir="./res/values/" overwrite="true"> - <filterset refid="maps-key" /> - <filterset> - <filter token="ocde.okapi.consumer.key" value="${ocde.okapi.consumer.key}"/> - <filter token="ocde.okapi.consumer.secret" value="${ocde.okapi.consumer.secret}"/> - <filter token="ocpl.okapi.consumer.key" value="${ocpl.okapi.consumer.key}"/> - <filter token="ocpl.okapi.consumer.secret" value="${ocpl.okapi.consumer.secret}"/> - <filter token="ocus.okapi.consumer.key" value="${ocus.okapi.consumer.key}"/> - <filter token="ocus.okapi.consumer.secret" value="${ocus.okapi.consumer.secret}"/> - <filter token="ocnl.okapi.consumer.key" value="${ocnl.okapi.consumer.key}"/> - <filter token="ocnl.okapi.consumer.secret" value="${ocnl.okapi.consumer.secret}"/> - <filter token="ocro.okapi.consumer.key" value="${ocro.okapi.consumer.key}"/> - <filter token="ocro.okapi.consumer.secret" value="${ocro.okapi.consumer.secret}"/> - <filter token="ocuk.okapi.consumer.key" value="${ocuk.okapi.consumer.key}"/> - <filter token="ocuk.okapi.consumer.secret" value="${ocuk.okapi.consumer.secret}"/> - </filterset> - </copy> - </target> + <target name="-pre-build"> + <!-- Enable ProGuard in debug builds --> + <condition property="proguard.enabled" value="true" else="false"> + <isset property="proguard.config" /> + </condition> + <if condition="${proguard.enabled}"> + <then> + <echo level="info">Proguard.config is enabled</echo> + <!-- Secondary dx input (jar files) is empty since all the jar files will be in the obfuscated jar --> + <path id="out.dex.jar.input.ref" /> + </then> + <else> + <echo level="info">Proguard.config is disabled</echo> + </else> + </if> + + <!-- Add all the keys for Google Maps, Twitter and OKAPI in the build --> + <condition property="build.mode.release" else="false"> + <equals arg1="${build.target}" arg2="release" /> + </condition> + <if condition="${build.mode.release}"> + <then> + <filterset id="maps-key"> + <filter token="maps.api.key" value="${maps.api.key.market}" /> + </filterset> + </then> + <else> + <filterset id="maps-key"> + <filter token="maps.api.key" value="${maps.api.key}"/> + </filterset> + </else> + </if> + <copy file="./templates/keys.xml" todir="./res/values/" overwrite="true"> + <filterset refid="maps-key" /> + <filterset> + <filter token="ocde.okapi.consumer.key" value="${ocde.okapi.consumer.key}"/> + <filter token="ocde.okapi.consumer.secret" value="${ocde.okapi.consumer.secret}"/> + <filter token="ocpl.okapi.consumer.key" value="${ocpl.okapi.consumer.key}"/> + <filter token="ocpl.okapi.consumer.secret" value="${ocpl.okapi.consumer.secret}"/> + <filter token="ocus.okapi.consumer.key" value="${ocus.okapi.consumer.key}"/> + <filter token="ocus.okapi.consumer.secret" value="${ocus.okapi.consumer.secret}"/> + <filter token="ocnl.okapi.consumer.key" value="${ocnl.okapi.consumer.key}"/> + <filter token="ocnl.okapi.consumer.secret" value="${ocnl.okapi.consumer.secret}"/> + <filter token="ocro.okapi.consumer.key" value="${ocro.okapi.consumer.key}"/> + <filter token="ocro.okapi.consumer.secret" value="${ocro.okapi.consumer.secret}"/> + <filter token="ocuk.okapi.consumer.key" value="${ocuk.okapi.consumer.key}"/> + <filter token="ocuk.okapi.consumer.secret" value="${ocuk.okapi.consumer.secret}"/> + </filterset> + </copy> + </target> -<!-- start of modifications for android annotations, see https://github.com/excilys/androidannotations/wiki/Building-Project-Ant --> + <!-- start of modifications for android annotations, see https://github.com/excilys/androidannotations/wiki/Building-Project-Ant --> <property name="generated.dir" value="annotation_gen" /> <property name="generated.absolute.dir" location="${generated.dir}" /> - <property name="java.compilerargs" value="-s '${generated.absolute.dir}'" /> + <property name="java.compilerargs" value="-s '${generated.absolute.dir}'" /> <target name="-pre-compile"> <mkdir dir="${generated.absolute.dir}" /> </target> - <target name="-compile" depends="-pre-build, -build-setup, -code-gen, -pre-compile"> - <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..."> - <!-- merge the project's own classpath and the tested project's classpath --> - <path id="project.javac.classpath"> - <path refid="project.all.jars.path" /> - <path refid="tested.project.classpath" /> - <path path="${java.compiler.classpath}" /> - <fileset dir="compile-libs" includes="*.jar"/> - </path> - <javac encoding="${java.encoding}" + <target name="-compile" depends="-pre-build, -build-setup, -code-gen, -pre-compile"> + <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..."> + <!-- merge the project's own classpath and the tested project's classpath --> + <path id="project.javac.classpath"> + <path refid="project.all.jars.path" /> + <path refid="tested.project.classpath" /> + <path path="${java.compiler.classpath}" /> + <fileset dir="compile-libs" includes="*.jar"/> + </path> + <javac encoding="${java.encoding}" source="${java.source}" target="${java.target}" debug="true" extdirs="" includeantruntime="false" destdir="${out.classes.absolute.dir}" @@ -149,77 +177,77 @@ verbose="${verbose}" classpathref="project.javac.classpath" fork="${need.javac.fork}"> - <src path="${source.absolute.dir}" /> - <src path="${gen.absolute.dir}" /> - <compilerarg line="${java.compilerargs}" /> - </javac> - - <!-- if the project is instrumented, intrument the classes --> - <if condition="${build.is.instrumented}"> - <then> - <echo level="info">Instrumenting classes from ${out.absolute.dir}/classes...</echo> - - <!-- build the filter to remove R, Manifest, BuildConfig --> - <getemmafilter + <src path="${source.absolute.dir}" /> + <src path="${gen.absolute.dir}" /> + <compilerarg line="${java.compilerargs}" /> + </javac> + + <!-- if the project is instrumented, intrument the classes --> + <if condition="${build.is.instrumented}"> + <then> + <echo level="info">Instrumenting classes from ${out.absolute.dir}/classes...</echo> + + <!-- build the filter to remove R, Manifest, BuildConfig --> + <getemmafilter appPackage="${project.app.package}" libraryPackagesRefId="project.library.packages" filterOut="emma.default.filter"/> - <!-- define where the .em file is going. This may have been + <!-- define where the .em file is going. This may have been setup already if this is a library --> - <property name="emma.coverage.absolute.file" location="${out.absolute.dir}/coverage.em" /> + <property name="emma.coverage.absolute.file" location="${out.absolute.dir}/coverage.em" /> - <!-- It only instruments class files, not any external libs --> - <emma enabled="true"> - <instr verbosity="${verbosity}" + <!-- It only instruments class files, not any external libs --> + <emma enabled="true"> + <instr verbosity="${verbosity}" mode="overwrite" instrpath="${out.absolute.dir}/classes" outdir="${out.absolute.dir}/classes" metadatafile="${emma.coverage.absolute.file}"> - <filter excludes="${emma.default.filter}" /> - <filter excludes="android.*, com.*, org.*" /> - <filter value="${emma.filter}" /> - </instr> - </emma> - </then> - </if> - - <!-- if the project is a library then we generate a jar file --> - <if condition="${project.is.library}"> - <then> - <echo level="info">Creating library output jar file...</echo> - <property name="out.library.jar.file" location="${out.absolute.dir}/classes.jar" /> - <if> - <condition> - <length string="${android.package.excludes}" trim="true" when="greater" length="0" /> - </condition> - <then> - <echo level="info">Custom jar packaging exclusion: ${android.package.excludes}</echo> - </then> - </if> - - <propertybyreplace name="project.app.package.path" input="${project.app.package}" replace="." with="/" /> - - <jar destfile="${out.library.jar.file}"> - <fileset dir="${out.classes.absolute.dir}" + <filter excludes="${emma.default.filter}" /> + <filter excludes="android.*, com.*, org.*" /> + <filter value="${emma.filter}" /> + </instr> + </emma> + </then> + </if> + + <!-- if the project is a library then we generate a jar file --> + <if condition="${project.is.library}"> + <then> + <echo level="info">Creating library output jar file...</echo> + <property name="out.library.jar.file" location="${out.absolute.dir}/classes.jar" /> + <if> + <condition> + <length string="${android.package.excludes}" trim="true" when="greater" length="0" /> + </condition> + <then> + <echo level="info">Custom jar packaging exclusion: ${android.package.excludes}</echo> + </then> + </if> + + <propertybyreplace name="project.app.package.path" input="${project.app.package}" replace="." with="/" /> + + <jar destfile="${out.library.jar.file}"> + <fileset dir="${out.classes.absolute.dir}" includes="**/*.class" excludes="${project.app.package.path}/R.class ${project.app.package.path}/R$*.class ${project.app.package.path}/BuildConfig.class"/> - <fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" /> - </jar> - </then> - </if> + <fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" /> + </jar> + </then> + </if> - </do-only-if-manifest-hasCode> - </target> -<!-- end of modifications for android-annotations --> - - -<!-- + </do-only-if-manifest-hasCode> + </target> + <!-- end of modifications for android-annotations --> + + + <!-- <target name="-post-compile"> </target> --> - <!-- Import the actual build file. + <!-- Import the actual build file. To customize existing targets, there are two options: - Customize only one target: @@ -237,7 +265,7 @@ In all cases you must update the value of version-tag below to read 'custom' instead of an integer, in order to avoid having your file be overridden by tools such as "android update project" --> - <!-- version-tag: custom --> - <import file="${sdk.dir}/tools/ant/build.xml" /> + <!-- version-tag: custom --> + <import file="${sdk.dir}/tools/ant/build.xml" /> </project> diff --git a/main/cgeo.iml b/main/cgeo.iml index 7ba7ab9..bb3a4d2 100644 --- a/main/cgeo.iml +++ b/main/cgeo.iml @@ -6,12 +6,16 @@ <proGuardCfgFiles> <file>file://$MODULE_DIR$/proguard-project.txt</file> </proGuardCfgFiles> + <option name="UPDATE_PROPERTY_FILES" value="false" /> <includeAssetsFromLibraries>true</includeAssetsFromLibraries> </configuration> </facet> </component> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> + <annotation-paths> + <root url="file://$MODULE_DIR$/project/annotations" /> + </annotation-paths> <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" /> @@ -19,6 +23,9 @@ </content> <orderEntry type="module-library" exported=""> <library name="libs"> + <ANNOTATIONS> + <root url="file://$MODULE_DIR$/project/annotations" /> + </ANNOTATIONS> <CLASSES> <root url="file://$MODULE_DIR$/libs" /> </CLASSES> @@ -39,14 +46,11 @@ <root url="file://$MODULE_DIR$/compile-libs" /> </CLASSES> <JAVADOC /> - <SOURCES> - <root url="file://$MODULE_DIR$/compile-libs" /> - </SOURCES> + <SOURCES /> <jarDirectory url="file://$MODULE_DIR$/compile-libs" recursive="false" /> - <jarDirectory url="file://$MODULE_DIR$/compile-libs" recursive="false" type="SOURCES" /> </library> </orderEntry> - <orderEntry type="module-library" exported="" scope="PROVIDED"> + <orderEntry type="module-library" exported=""> <library> <CLASSES> <root url="file://$MODULE_DIR$/libs" /> @@ -59,6 +63,206 @@ <orderEntry type="module" module-name="mapswithme-api" exported="" /> <orderEntry type="module" module-name="showcaseview" exported="" /> <orderEntry type="module" module-name="android-support-v7-appcompat" exported="" /> + <orderEntry type="module" module-name="play-services-base" exported="" /> + <orderEntry type="module" module-name="play-services-location" exported="" /> + </component> + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> </component> -</module> - +</module>
\ No newline at end of file diff --git a/main/compile-libs/androidannotations-3.0.1.jar b/main/compile-libs/androidannotations-3.0.1.jar Binary files differdeleted file mode 100644 index 4c96d6c..0000000 --- a/main/compile-libs/androidannotations-3.0.1.jar +++ /dev/null diff --git a/main/compile-libs/androidannotations-3.2.jar b/main/compile-libs/androidannotations-3.2.jar Binary files differnew file mode 100644 index 0000000..9f40472 --- /dev/null +++ b/main/compile-libs/androidannotations-3.2.jar diff --git a/main/libs/androidannotations-api-3.0.1.jar b/main/libs/androidannotations-api-3.0.1.jar Binary files differdeleted file mode 100644 index 90bfe7a..0000000 --- a/main/libs/androidannotations-api-3.0.1.jar +++ /dev/null diff --git a/main/libs/androidannotations-api-3.2.jar b/main/libs/androidannotations-api-3.2.jar Binary files differnew file mode 100644 index 0000000..12d4ef0 --- /dev/null +++ b/main/libs/androidannotations-api-3.2.jar diff --git a/main/libs/androidannotations-api-3.2.jar.properties b/main/libs/androidannotations-api-3.2.jar.properties new file mode 100644 index 0000000..6e05cd2 --- /dev/null +++ b/main/libs/androidannotations-api-3.2.jar.properties @@ -0,0 +1,2 @@ +src=src/androidannotations-api-3.2-sources.jar +doc=src/androidannotations-api-3.2-javadoc.jar
\ No newline at end of file diff --git a/main/libs/findbugs-annotations.jar b/main/libs/annotations-3.0.0.jar Binary files differindex 3641ad6..a2f68fe 100644 --- a/main/libs/findbugs-annotations.jar +++ b/main/libs/annotations-3.0.0.jar diff --git a/main/libs/annotations-3.0.0.jar.properties b/main/libs/annotations-3.0.0.jar.properties new file mode 100644 index 0000000..a32a2ea --- /dev/null +++ b/main/libs/annotations-3.0.0.jar.properties @@ -0,0 +1,2 @@ +src=src/annotations-3.0.0-sources.jar +doc=src/annotations-3.0.0-javadoc.jar diff --git a/main/libs/butterknife-5.1.1.jar b/main/libs/butterknife-5.1.1.jar Binary files differdeleted file mode 100644 index 45ab11f..0000000 --- a/main/libs/butterknife-5.1.1.jar +++ /dev/null diff --git a/main/libs/butterknife-6.1.0.jar b/main/libs/butterknife-6.1.0.jar Binary files differnew file mode 100644 index 0000000..699077a --- /dev/null +++ b/main/libs/butterknife-6.1.0.jar diff --git a/main/libs/butterknife-6.1.0.jar.properties b/main/libs/butterknife-6.1.0.jar.properties new file mode 100644 index 0000000..3db4372 --- /dev/null +++ b/main/libs/butterknife-6.1.0.jar.properties @@ -0,0 +1,2 @@ +src=src/butterknife-6.1.0-sources.jar +doc=src/butterknife-6.1.0-javadoc.jar diff --git a/main/libs/commons-collections4-4.0.jar.properties b/main/libs/commons-collections4-4.0.jar.properties index a50b66c..1807323 100644 --- a/main/libs/commons-collections4-4.0.jar.properties +++ b/main/libs/commons-collections4-4.0.jar.properties @@ -1 +1,2 @@ -src=src/commons-collections4-4.0-sources.jar
\ No newline at end of file +src=src/commons-collections4-4.0-sources.jar +doc=src/commons-collections4-4.0-javadoc.jar diff --git a/main/libs/commons-io-2.4.jar.properties b/main/libs/commons-io-2.4.jar.properties index d160263..ff1c9c9 100644 --- a/main/libs/commons-io-2.4.jar.properties +++ b/main/libs/commons-io-2.4.jar.properties @@ -1,2 +1,2 @@ src=src/commons-io-2.4-sources.jar -doc=src/commons-io-2.4-javadoc.jar
\ No newline at end of file +doc=src/commons-io-2.4-javadoc.jar diff --git a/main/libs/commons-lang3-3.3.2.jar b/main/libs/commons-lang3-3.3.2.jar Binary files differindex bb06979..2ce08ae 100644 --- a/main/libs/commons-lang3-3.3.2.jar +++ b/main/libs/commons-lang3-3.3.2.jar diff --git a/main/libs/commons-lang3-3.3.2.jar.properties b/main/libs/commons-lang3-3.3.2.jar.properties index 0885ede..08f905f 100644 --- a/main/libs/commons-lang3-3.3.2.jar.properties +++ b/main/libs/commons-lang3-3.3.2.jar.properties @@ -1 +1,2 @@ -doc=src/commons-lang3-3.3.2-javadoc.jar
\ No newline at end of file +src=src/commons-lang3-3.3.2-sources.jar +doc=src/commons-lang3-3.3.2-javadoc.jar diff --git a/main/libs/jackson-annotations-2.5.1.jar b/main/libs/jackson-annotations-2.5.1.jar Binary files differnew file mode 100644 index 0000000..9bce595 --- /dev/null +++ b/main/libs/jackson-annotations-2.5.1.jar diff --git a/main/libs/jackson-annotations-2.5.1.jar.properties b/main/libs/jackson-annotations-2.5.1.jar.properties new file mode 100644 index 0000000..d96e699 --- /dev/null +++ b/main/libs/jackson-annotations-2.5.1.jar.properties @@ -0,0 +1,2 @@ +src=src/jackson-annotations-2.5.1-sources.jar +doc=src/jackson-annotations-2.5.1-javadoc.jar diff --git a/main/libs/jackson-core-2.5.1.jar b/main/libs/jackson-core-2.5.1.jar Binary files differnew file mode 100644 index 0000000..8c9c4e0 --- /dev/null +++ b/main/libs/jackson-core-2.5.1.jar diff --git a/main/libs/jackson-core-2.5.1.jar.properties b/main/libs/jackson-core-2.5.1.jar.properties new file mode 100644 index 0000000..c32e143 --- /dev/null +++ b/main/libs/jackson-core-2.5.1.jar.properties @@ -0,0 +1,2 @@ +src=src/jackson-core-2.5.1-sources.jar +doc=src/jackson-core-2.5.1-javadoc.jar diff --git a/main/libs/jackson-databind-2.5.1.jar b/main/libs/jackson-databind-2.5.1.jar Binary files differnew file mode 100644 index 0000000..9b82e3f --- /dev/null +++ b/main/libs/jackson-databind-2.5.1.jar diff --git a/main/libs/jackson-databind-2.5.1.jar.properties b/main/libs/jackson-databind-2.5.1.jar.properties new file mode 100644 index 0000000..8fefb06 --- /dev/null +++ b/main/libs/jackson-databind-2.5.1.jar.properties @@ -0,0 +1,2 @@ +src=src/jackson-databind-2.5.1-sources.jar +doc=src/jackson-databind-2.5.1-javadoc.jar diff --git a/main/libs/mapsforge-map-0.2.4.jar b/main/libs/mapsforge-map-0.2.4.jar Binary files differdeleted file mode 100644 index ec9aa4c..0000000 --- a/main/libs/mapsforge-map-0.2.4.jar +++ /dev/null diff --git a/main/libs/rxandroid-0.24.0.jar b/main/libs/rxandroid-0.24.0.jar Binary files differnew file mode 100644 index 0000000..35eb088 --- /dev/null +++ b/main/libs/rxandroid-0.24.0.jar diff --git a/main/libs/rxandroid-0.24.0.jar.properties b/main/libs/rxandroid-0.24.0.jar.properties new file mode 100644 index 0000000..d995320 --- /dev/null +++ b/main/libs/rxandroid-0.24.0.jar.properties @@ -0,0 +1,2 @@ +src=src/rxandroid-0.24.0-sources.jar +doc=src/rxandroid-0.24.0-javadoc.jar diff --git a/main/libs/rxjava-1.0.8.jar b/main/libs/rxjava-1.0.8.jar Binary files differnew file mode 100644 index 0000000..f60ebe1 --- /dev/null +++ b/main/libs/rxjava-1.0.8.jar diff --git a/main/libs/rxjava-1.0.8.jar.properties b/main/libs/rxjava-1.0.8.jar.properties new file mode 100644 index 0000000..757e3be --- /dev/null +++ b/main/libs/rxjava-1.0.8.jar.properties @@ -0,0 +1,2 @@ +src=src/rxjava-1.0.8-sources.jar +doc=src/rxjava-1.0.8-javadoc.jar diff --git a/main/libs/rxjava-android-0.19.6.jar b/main/libs/rxjava-android-0.19.6.jar Binary files differdeleted file mode 100644 index ccc8b6a..0000000 --- a/main/libs/rxjava-android-0.19.6.jar +++ /dev/null diff --git a/main/libs/rxjava-android-0.19.6.jar.properties b/main/libs/rxjava-android-0.19.6.jar.properties deleted file mode 100644 index 7414a89..0000000 --- a/main/libs/rxjava-android-0.19.6.jar.properties +++ /dev/null @@ -1,2 +0,0 @@ -src=src/rxjava-android-0.19.6-sources.jar -doc=src/rxjava-android-0.19.6-javadoc.jar diff --git a/main/libs/rxjava-async-util-0.19.6.jar b/main/libs/rxjava-async-util-0.19.6.jar Binary files differdeleted file mode 100644 index 93c1a9b..0000000 --- a/main/libs/rxjava-async-util-0.19.6.jar +++ /dev/null diff --git a/main/libs/rxjava-async-util-0.19.6.jar.properties b/main/libs/rxjava-async-util-0.19.6.jar.properties deleted file mode 100644 index 0396d9a..0000000 --- a/main/libs/rxjava-async-util-0.19.6.jar.properties +++ /dev/null @@ -1,2 +0,0 @@ -src=src/rxjava-async-util-0.19.6-sources.jar -doc=src/rxjava-async-util-0.19.6-javadoc.jar diff --git a/main/libs/rxjava-core-0.19.6.jar b/main/libs/rxjava-core-0.19.6.jar Binary files differdeleted file mode 100644 index 9b6cbfa..0000000 --- a/main/libs/rxjava-core-0.19.6.jar +++ /dev/null diff --git a/main/libs/rxjava-core-0.19.6.jar.properties b/main/libs/rxjava-core-0.19.6.jar.properties deleted file mode 100644 index 41b8394..0000000 --- a/main/libs/rxjava-core-0.19.6.jar.properties +++ /dev/null @@ -1,2 +0,0 @@ -src=src/rxjava-core-0.19.6-sources.jar -doc=src/rxjava-core-0.19.6-javadoc.jar diff --git a/main/libs/src/androidannotations-api-3.2-javadoc.jar b/main/libs/src/androidannotations-api-3.2-javadoc.jar Binary files differnew file mode 100644 index 0000000..efdaf1f --- /dev/null +++ b/main/libs/src/androidannotations-api-3.2-javadoc.jar diff --git a/main/libs/src/androidannotations-api-3.2-sources.jar b/main/libs/src/androidannotations-api-3.2-sources.jar Binary files differnew file mode 100644 index 0000000..acc6ba9 --- /dev/null +++ b/main/libs/src/androidannotations-api-3.2-sources.jar diff --git a/main/libs/src/annotations-3.0.0-javadoc.jar b/main/libs/src/annotations-3.0.0-javadoc.jar Binary files differnew file mode 100644 index 0000000..0098501 --- /dev/null +++ b/main/libs/src/annotations-3.0.0-javadoc.jar diff --git a/main/libs/src/annotations-3.0.0-sources.jar b/main/libs/src/annotations-3.0.0-sources.jar Binary files differnew file mode 100644 index 0000000..0098501 --- /dev/null +++ b/main/libs/src/annotations-3.0.0-sources.jar diff --git a/main/libs/src/butterknife-6.1.0-javadoc.jar b/main/libs/src/butterknife-6.1.0-javadoc.jar Binary files differnew file mode 100644 index 0000000..44577e4 --- /dev/null +++ b/main/libs/src/butterknife-6.1.0-javadoc.jar diff --git a/main/libs/src/butterknife-6.1.0-sources.jar b/main/libs/src/butterknife-6.1.0-sources.jar Binary files differnew file mode 100644 index 0000000..f980a1d --- /dev/null +++ b/main/libs/src/butterknife-6.1.0-sources.jar diff --git a/main/libs/src/commons-collections4-4.0-javadoc.jar b/main/libs/src/commons-collections4-4.0-javadoc.jar Binary files differnew file mode 100644 index 0000000..35989f8 --- /dev/null +++ b/main/libs/src/commons-collections4-4.0-javadoc.jar diff --git a/main/libs/src/commons-lang3-3.3.2-javadoc.jar b/main/libs/src/commons-lang3-3.3.2-javadoc.jar Binary files differindex bd2f422..9cad4b1 100644 --- a/main/libs/src/commons-lang3-3.3.2-javadoc.jar +++ b/main/libs/src/commons-lang3-3.3.2-javadoc.jar diff --git a/main/libs/src/commons-lang3-3.3.2-sources.jar b/main/libs/src/commons-lang3-3.3.2-sources.jar Binary files differnew file mode 100644 index 0000000..fa12693 --- /dev/null +++ b/main/libs/src/commons-lang3-3.3.2-sources.jar diff --git a/main/libs/src/jackson-annotations-2.5.1-javadoc.jar b/main/libs/src/jackson-annotations-2.5.1-javadoc.jar Binary files differnew file mode 100644 index 0000000..d4d2c55 --- /dev/null +++ b/main/libs/src/jackson-annotations-2.5.1-javadoc.jar diff --git a/main/libs/src/jackson-annotations-2.5.1-sources.jar b/main/libs/src/jackson-annotations-2.5.1-sources.jar Binary files differnew file mode 100644 index 0000000..a7f0358 --- /dev/null +++ b/main/libs/src/jackson-annotations-2.5.1-sources.jar diff --git a/main/libs/src/jackson-core-2.5.1-javadoc.jar b/main/libs/src/jackson-core-2.5.1-javadoc.jar Binary files differnew file mode 100644 index 0000000..a7f96ce --- /dev/null +++ b/main/libs/src/jackson-core-2.5.1-javadoc.jar diff --git a/main/libs/src/jackson-core-2.5.1-sources.jar b/main/libs/src/jackson-core-2.5.1-sources.jar Binary files differnew file mode 100644 index 0000000..fd77726 --- /dev/null +++ b/main/libs/src/jackson-core-2.5.1-sources.jar diff --git a/main/libs/src/jackson-databind-2.5.1-javadoc.jar b/main/libs/src/jackson-databind-2.5.1-javadoc.jar Binary files differnew file mode 100644 index 0000000..1ea90be --- /dev/null +++ b/main/libs/src/jackson-databind-2.5.1-javadoc.jar diff --git a/main/libs/src/jackson-databind-2.5.1-sources.jar b/main/libs/src/jackson-databind-2.5.1-sources.jar Binary files differnew file mode 100644 index 0000000..8ca50ff --- /dev/null +++ b/main/libs/src/jackson-databind-2.5.1-sources.jar diff --git a/main/libs/src/rxandroid-0.24.0-javadoc.jar b/main/libs/src/rxandroid-0.24.0-javadoc.jar Binary files differnew file mode 100644 index 0000000..ea887e5 --- /dev/null +++ b/main/libs/src/rxandroid-0.24.0-javadoc.jar diff --git a/main/libs/src/rxandroid-0.24.0-sources.jar b/main/libs/src/rxandroid-0.24.0-sources.jar Binary files differnew file mode 100644 index 0000000..8bffa81 --- /dev/null +++ b/main/libs/src/rxandroid-0.24.0-sources.jar diff --git a/main/libs/src/rxjava-1.0.8-javadoc.jar b/main/libs/src/rxjava-1.0.8-javadoc.jar Binary files differnew file mode 100644 index 0000000..59c118d --- /dev/null +++ b/main/libs/src/rxjava-1.0.8-javadoc.jar diff --git a/main/libs/src/rxjava-1.0.8-sources.jar b/main/libs/src/rxjava-1.0.8-sources.jar Binary files differnew file mode 100644 index 0000000..4fc97d2 --- /dev/null +++ b/main/libs/src/rxjava-1.0.8-sources.jar diff --git a/main/libs/src/rxjava-android-0.19.6-javadoc.jar b/main/libs/src/rxjava-android-0.19.6-javadoc.jar Binary files differdeleted file mode 100644 index a92ab4f..0000000 --- a/main/libs/src/rxjava-android-0.19.6-javadoc.jar +++ /dev/null diff --git a/main/libs/src/rxjava-android-0.19.6-sources.jar b/main/libs/src/rxjava-android-0.19.6-sources.jar Binary files differdeleted file mode 100644 index ea4eba0..0000000 --- a/main/libs/src/rxjava-android-0.19.6-sources.jar +++ /dev/null diff --git a/main/libs/src/rxjava-async-util-0.19.6-javadoc.jar b/main/libs/src/rxjava-async-util-0.19.6-javadoc.jar Binary files differdeleted file mode 100644 index f943e5f..0000000 --- a/main/libs/src/rxjava-async-util-0.19.6-javadoc.jar +++ /dev/null diff --git a/main/libs/src/rxjava-async-util-0.19.6-sources.jar b/main/libs/src/rxjava-async-util-0.19.6-sources.jar Binary files differdeleted file mode 100644 index 82ca499..0000000 --- a/main/libs/src/rxjava-async-util-0.19.6-sources.jar +++ /dev/null diff --git a/main/libs/src/rxjava-core-0.19.6-javadoc.jar b/main/libs/src/rxjava-core-0.19.6-javadoc.jar Binary files differdeleted file mode 100644 index 5523ee0..0000000 --- a/main/libs/src/rxjava-core-0.19.6-javadoc.jar +++ /dev/null diff --git a/main/libs/src/rxjava-core-0.19.6-sources.jar b/main/libs/src/rxjava-core-0.19.6-sources.jar Binary files differdeleted file mode 100644 index 0c2aa68..0000000 --- a/main/libs/src/rxjava-core-0.19.6-sources.jar +++ /dev/null diff --git a/main/lint.xml b/main/lint.xml index 905b9a4..60a2d28 100644 --- a/main/lint.xml +++ b/main/lint.xml @@ -12,6 +12,8 @@ </issue> <issue id="MissingTranslation" severity="ignore" /> <issue id="Registered" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> <issue id="UnusedAttribute" severity="ignore" /> <issue id="UnusedResources"> <ignore path="res/drawable-mdpi/attribute_maintenance.png" /> diff --git a/main/proguard-project.txt b/main/proguard-project.txt index 2a27d99..230d85f 100644 --- a/main/proguard-project.txt +++ b/main/proguard-project.txt @@ -21,9 +21,12 @@ # rxjava internal references sun.misc.Unsafe -dontwarn sun.misc.Unsafe +# jackson internal references +-dontwarn org.w3c.dom.bootstrap.DOMImplementationRegistry + #-dontnote org.apache.commons.logging.** --keep public class cgeo.geocaching.* +-keep class cgeo.geocaching.** { *; } -keep class android.support.v4.os.** { *; } -keep class ch.boye.httpclientandroidlib.conn.scheme.Scheme { *; } @@ -59,7 +62,19 @@ # Null analysis annotations of Eclipse JDT are just used by the Eclipse compiler, so ignore them here -dontwarn org.eclipse.jdt.annotation.** +# keep Emma code coverage during debug builds, and ignore related warnings +-keep class com.vladium.** { *; } +-dontwarn com.vladium.** + +# keep some test only utils classes +-keep class org.apache.commons.lang3.StringUtils { *; } +-keep class org.apache.commons.io.IOUtils { *; } +-keep class org.apache.commons.io.FileUtils { *; } + # action providers are only referenced from XML -keep public class cgeo.geocaching.sorting.SortActionProvider { *; } -keep public class cgeo.geocaching.ui.NavigationActionProvider { *; } --keep public class cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider { *; }
\ No newline at end of file +-keep public class cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider { *; } + +# Play Service references to classes introduced in higher API levels +-dontwarn com.google.android.gms.** diff --git a/main/project.properties b/main/project.properties index b341d6c..600d70f 100644 --- a/main/project.properties +++ b/main/project.properties @@ -8,12 +8,14 @@ # project structure. # # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt +proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt:../play-services-base/proguard.txt:../play-services-location/proguard.txt # Project target. -target=android-19 +target=android-21 android.library.reference.1=../mapswithme-api android.library.reference.2=../android-support-v7-appcompat +android.library.reference.3=../showcaseview java.source=1.7 java.target=1.7 -android.library.reference.3=../showcaseview +android.library.reference.4=../play-services-base +android.library.reference.5=../play-services-location diff --git a/main/project/annotations/java/lang/annotations.xml b/main/project/annotations/java/lang/annotations.xml new file mode 100644 index 0000000..0926f42 --- /dev/null +++ b/main/project/annotations/java/lang/annotations.xml @@ -0,0 +1,7 @@ +<root> + <item name='java.lang.String java.lang.String trim()'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""->!null"" /> + </annotation> + </item> +</root>
\ No newline at end of file diff --git a/main/project/annotations/java/util/annotations.xml b/main/project/annotations/java/util/annotations.xml new file mode 100644 index 0000000..854909b --- /dev/null +++ b/main/project/annotations/java/util/annotations.xml @@ -0,0 +1,7 @@ +<root> + <item name='java.util.List java.lang.Object[] toArray()'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""->!null"" /> + </annotation> + </item> +</root>
\ No newline at end of file diff --git a/main/project/annotations/org/apache/commons/lang3/annotations.xml b/main/project/annotations/org/apache/commons/lang3/annotations.xml new file mode 100644 index 0000000..0ed3c67 --- /dev/null +++ b/main/project/annotations/org/apache/commons/lang3/annotations.xml @@ -0,0 +1,34 @@ +<root> + <item name='org.apache.commons.lang3.StringUtils boolean isNotBlank(java.lang.CharSequence)'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""null->false"" /> + </annotation> + </item> + <item + name='org.apache.commons.lang3.StringUtils boolean startsWith(java.lang.CharSequence, java.lang.CharSequence)'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""null,null->true;null,!null->false;!null,null->false"" /> + </annotation> + </item> + <item + name='org.apache.commons.lang3.StringUtils java.lang.String substringBetween(java.lang.String, java.lang.String, java.lang.String)'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""null,_,_->null;_,null,_->null;_,_,null->null"" /> + </annotation> + </item> + <item name='org.apache.commons.lang3.StringUtils java.lang.String trim(java.lang.String)'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""null->null;!null->!null"" /> + </annotation> + </item> + <item name='org.apache.commons.lang3.StringUtils java.lang.String upperCase(java.lang.String)'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""null->null;!null->!null"" /> + </annotation> + </item> + <item name='org.apache.commons.lang3.StringUtils java.lang.String[] split(java.lang.String)'> + <annotation name='org.jetbrains.annotations.Contract'> + <val val=""null->null;!null->!null"" /> + </annotation> + </item> +</root>
\ No newline at end of file diff --git a/main/project/eclipse installation/cgeo eclipse components.p2f b/main/project/eclipse installation/cgeo eclipse components.p2f index f758e68..edac095 100644 --- a/main/project/eclipse installation/cgeo eclipse components.p2f +++ b/main/project/eclipse installation/cgeo eclipse components.p2f @@ -1,40 +1,95 @@ <?xml version='1.0' encoding='UTF-8'?> <?p2f version='1.0.0'?> <p2f version='1.0.0'> - <ius size='7'> - <iu id='com.android.ide.eclipse.ddms.feature.group' name='Android DDMS' version='22.2.1.v201309180102-833290'> + <ius size='18'> + <iu id='com.android.ide.eclipse.ddms.feature.feature.group' name='Android DDMS' version='23.0.4.1468518'> <repositories size='1'> <repository location='https://dl-ssl.google.com/android/eclipse/'/> </repositories> </iu> - <iu id='com.android.ide.eclipse.adt.feature.group' name='Android Development Tools' version='22.2.1.v201309180102-833290'> + <iu id='com.android.ide.eclipse.adt.feature.feature.group' name='Android Development Tools' version='23.0.4.1468518'> <repositories size='1'> <repository location='https://dl-ssl.google.com/android/eclipse/'/> </repositories> </iu> - <iu id='com.android.ide.eclipse.hierarchyviewer.feature.group' name='Android Hierarchy Viewer' version='22.2.1.v201309180102-833290'> + <iu id='com.android.ide.eclipse.hierarchyviewer.feature.feature.group' name='Android Hierarchy Viewer' version='23.0.4.1468518'> <repositories size='1'> <repository location='https://dl-ssl.google.com/android/eclipse/'/> </repositories> </iu> - <iu id='com.android.ide.eclipse.traceview.feature.group' name='Android Traceview' version='22.2.1.v201309180102-833290'> + <iu id='com.android.ide.eclipse.traceview.feature.feature.group' name='Android Traceview' version='23.0.4.1468518'> <repositories size='1'> <repository location='https://dl-ssl.google.com/android/eclipse/'/> </repositories> </iu> - <iu id='org.eclipse.mylyn.github.feature.feature.group' name='Eclipse GitHub integration with task focused interface' version='3.0.0.201306101825-r'> + <iu id='org.eclipse.recommenders.mylyn.rcp.feature.feature.group' name='Code Recommenders Mylyn Integration' version='2.1.9.v20140917-1240'> <repositories size='1'> - <repository location='http://download.eclipse.org/releases/kepler'/> + <repository location='http://download.eclipse.org/releases/luna'/> </repositories> </iu> - <iu id='epp.package.java' name='Eclipse IDE for Java Developers' version='2.0.1.20130919-0803'> + <iu id='org.eclipse.recommenders.snipmatch.rcp.feature.feature.group' name='Code Recommenders Snipmatch' version='2.1.9.v20140917-1240'> <repositories size='1'> - <repository location='http://download.eclipse.org/releases/kepler'/> + <repository location='http://download.eclipse.org/releases/luna'/> </repositories> </iu> - <iu id='edu.umd.cs.findbugs.plugin.eclipse.feature.group' name='FindBugs Feature' version='2.0.2.20121210'> + <iu id='org.eclipse.mylyn.github.feature.feature.group' name='Eclipse GitHub integration with task focused interface' version='3.5.0.201409260305-r'> <repositories size='1'> - <repository location='http://findbugs.cs.umd.edu/eclipse'/> + <repository location='http://download.eclipse.org/egit/github/updates'/> + </repositories> + </iu> + <iu id='epp.package.java' name='Eclipse IDE for Java Developers' version='4.4.1.20140925-1820'> + <repositories size='1'> + <repository location='http://download.eclipse.org/releases/luna'/> + </repositories> + </iu> + <iu id='edu.umd.cs.findbugs.plugin.eclipse.feature.group' name='FindBugs Feature' version='3.0.0.20140706-2cfb468'> + <repositories size='1'> + <repository location='http://findbugs.cs.umd.edu/eclipse/'/> + </repositories> + </iu> + <iu id='com.genymobile.genymotion.ide.eclipse.feature.group' name='Genymotion Eclipse Tools' version='1.0.3.201403261147'> + <repositories size='1'> + <repository location='http://plugins.genymotion.com/eclipse'/> + </repositories> + </iu> + <iu id='org.springsource.ide.eclipse.gradle.feature.feature.group' name='Gradle IDE' version='3.6.1.201408250705-RELEASE'> + <repositories size='1'> + <repository location='http://dist.springsource.com/release/TOOLS/gradle'/> + </repositories> + </iu> + <iu id='org.eclipse.jgit.http.apache.feature.group' name='Java implementation of Git - optional Http support using Apache httpclient' version='3.5.0.201409260305-r'> + <repositories size='1'> + <repository location='http://download.eclipse.org/egit/updates'/> + </repositories> + </iu> + <iu id='org.eclipse.jgit.java7.feature.group' name='Java implementation of Git - optional Java 7 libraries' version='3.5.0.201409260305-r'> + <repositories size='1'> + <repository location='http://download.eclipse.org/egit/updates'/> + </repositories> + </iu> + <iu id='org.eclipse.wst.jsdt.feature.feature.group' name='JavaScript Development Tools' version='1.6.100.v201409111605'> + <repositories size='1'> + <repository location='http://download.eclipse.org/releases/luna'/> + </repositories> + </iu> + <iu id='markdown.editor.feature.feature.group' name='Markdown Editor' version='0.2.3'> + <repositories size='1'> + <repository location='http://www.winterwell.com/software/updatesite/'/> + </repositories> + </iu> + <iu id='org.moreunit.feature.group' name='MoreUnit For Java' version='3.0.4'> + <repositories size='1'> + <repository location='http://moreunit.sourceforge.net/update-site/'/> + </repositories> + </iu> + <iu id='org.projectusus.feature.group' name='Project Usus' version='0.7.4.201401122006'> + <repositories size='1'> + <repository location='http://projectusus.googlecode.com/svn/updates/'/> + </repositories> + </iu> + <iu id='com.android.ide.eclipse.gldebugger.feature.feature.group' name='Tracer for OpenGL ES' version='23.0.4.1468518'> + <repositories size='1'> + <repository location='https://dl-ssl.google.com/android/eclipse/'/> </repositories> </iu> </ius> diff --git a/main/project/libraries/.gitignore b/main/project/libraries/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/main/project/libraries/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/main/project/libraries/pom.xml b/main/project/libraries/pom.xml new file mode 100644 index 0000000..b59d4af --- /dev/null +++ b/main/project/libraries/pom.xml @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.cgeo</groupId> + <artifactId>library.check</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>c:geo dependency update check</name> + + <description>This project checks or updates c:geo dependencies. + Run 'mvn validate' to see available dependency updates. + Run 'mvn install' to actually update to the latest releases. You may need to refresh your IDE afterwards. + </description> + + <properties> + <AndroidAnnotationsVersion>3.2</AndroidAnnotationsVersion> + + <ButterKnifeVersion>6.1.0</ButterKnifeVersion> + + <CommonsCollections4Version>4.0</CommonsCollections4Version> + <CommonsIoVersion>2.4</CommonsIoVersion> + <CommonsLang3Version>3.3.2</CommonsLang3Version> + + <FindbugsAnnotationsVersion>3.0.0</FindbugsAnnotationsVersion> + + <JacksonAnnotationsVersion>2.5.1</JacksonAnnotationsVersion> + <JacksonCoreVersion>2.5.1</JacksonCoreVersion> + <JacksonDatabindVersion>2.5.1</JacksonDatabindVersion> + + <RXAndroidVersion>0.24.0</RXAndroidVersion> + <RXJavaVersion>1.0.7</RXJavaVersion> + </properties> + + <dependencies> + <dependency> + <groupId>org.androidannotations</groupId> + <artifactId>androidannotations</artifactId> + <version>${AndroidAnnotationsVersion}</version> + </dependency> + <dependency> + <groupId>org.androidannotations</groupId> + <artifactId>androidannotations-api</artifactId> + <version>${AndroidAnnotationsVersion}</version> + </dependency> + + <dependency> + <groupId>com.jakewharton</groupId> + <artifactId>butterknife</artifactId> + <version>${ButterKnifeVersion}</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>${CommonsCollections4Version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>${CommonsLang3Version}</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>${CommonsIoVersion}</version> + </dependency> + + <dependency> + <groupId>com.google.code.findbugs</groupId> + <artifactId>annotations</artifactId> + <version>${FindbugsAnnotationsVersion}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${JacksonAnnotationsVersion}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>${JacksonCoreVersion}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${JacksonDatabindVersion}</version> + </dependency> + + <dependency> + <groupId>io.reactivex</groupId> + <artifactId>rxjava</artifactId> + <version>${RXJavaVersion}</version> + </dependency> + <dependency> + <groupId>io.reactivex</groupId> + <artifactId>rxandroid</artifactId> + <version>${RXAndroidVersion}</version> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>versions-maven-plugin</artifactId> + <version>2.1</version> + <executions> + <execution> + <id>display-property-updates</id> + <phase>validate</phase> + <goals> + <goal>display-property-updates</goal> + </goals> + </execution> + <execution> + <id>update-properties</id> + <phase>package</phase> + <goals> + <goal>update-properties</goal> + </goals> + <configuration> + <allowSnapshots>false</allowSnapshots> + <allowMajorUpdates>true</allowMajorUpdates> + <allowMinorUpdates>true</allowMinorUpdates> + <generateBackupPoms>true</generateBackupPoms> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.9</version> + <executions> + <execution> + <id>copy-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <outputDirectory>${basedir}/../../libs</outputDirectory> + <overWriteReleases>true</overWriteReleases> + <excludeTransitive>true</excludeTransitive> + </configuration> + </execution> + <execution> + <id>src-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <classifier>sources</classifier> + <outputDirectory>${basedir}/../../libs/src</outputDirectory> + <failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact> + <overWriteReleases>true</overWriteReleases> + <excludeTransitive>true</excludeTransitive> + </configuration> + </execution> + <execution> + <id>javadoc-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <classifier>javadoc</classifier> + <outputDirectory>${basedir}/../../libs/src</outputDirectory> + <failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact> + <overWriteReleases>true</overWriteReleases> + <excludeTransitive>true</excludeTransitive> + </configuration> + </execution> + </executions> + </plugin> + <!-- unfinished: update properties files of source and javadoc + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.4</version> + <executions> + <execution> + <id>write-properties-files</id> + <phase>package</phase> + <configuration> + <tasks> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + --> + </plugins> + </build> +</project> diff --git a/main/project/libraries/update-libs.sh b/main/project/libraries/update-libs.sh index f2e9ced..4c66254 100755 --- a/main/project/libraries/update-libs.sh +++ b/main/project/libraries/update-libs.sh @@ -1,7 +1,14 @@ #! /bin/sh # -RXJAVA=0.19.6 +RXJAVA=1.0.8 +RXANDROID=0.24.0 +JACKSONCORE=2.5.1 +JACKSONDATABIND=2.5.1 +JACKSONANNOTATIONS=2.5.1 +COMMONSCOLLECTIONS4=4.0 +COMMONSLANG3=3.3.2 +COMMONSIO=2.4 cd $(git rev-parse --show-toplevel)/main/libs @@ -27,7 +34,21 @@ fixgradle() { sed -i "/def $var =/s/.*/def $var = '$version'/" ../build.gradle } -updatelib com/netflix/rxjava rxjava-core $RXJAVA -updatelib com/netflix/rxjava rxjava-android $RXJAVA -updatelib com/netflix/rxjava rxjava-async-util $RXJAVA -fixgradle RXVersion $RXJAVA +updatelib io/reactivex rxjava $RXJAVA +fixgradle RXJavaVersion $RXJAVA +updatelib io/reactivex rxandroid $RXANDROID +fixgradle RXAndroidVersion $RXANDROID + +updatelib com/fasterxml/jackson/core jackson-core $JACKSONCORE +fixgradle JacksonCoreVersion $JACKSONCORE +updatelib com/fasterxml/jackson/core jackson-databind $JACKSONDATABIND +fixgradle JacksonDatabindVersion $JACKSONDATABIND +updatelib com/fasterxml/jackson/core jackson-annotations $JACKSONANNOTATIONS +fixgradle JacksonAnnotationsVersion $JACKSONANNOTATIONS + +updatelib org/apache/commons commons-collections4 $COMMONSCOLLECTIONS4 +fixgradle CommonsCollections4Version $COMMONSCOLLECTIONS4 +updatelib org/apache/commons commons-lang3 $COMMONSLANG3 +fixgradle CommonsLang3Version $COMMONSLANG3 +updatelib commons-io commons-io $COMMONSIO +fixgradle CommonsIoVersion $COMMONSIO diff --git a/main/project/rawimages/new-idea-modified.svg b/main/project/rawimages/new-idea-modified.svg new file mode 100644 index 0000000..71e0966 --- /dev/null +++ b/main/project/rawimages/new-idea-modified.svg @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + x="0px" + y="0px" + viewBox="4.5 -9.0 90.0 121.5" + enable-background="new 0 0 90 90" + xml:space="preserve" + height="100px" + width="100px" + id="svg2" + inkscape:version="0.48.5 r10040" + sodipodi:docname="new-idea-modified.svg" + inkscape:export-filename="/home/rainer/Desktop/dev/android/cgeo_os/c-geo-opensource/main/project/rawimages/ic_menu_hint.png" + inkscape:export-xdpi="39.369999" + inkscape:export-ydpi="39.369999"><metadata + id="metadata37"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs35" /><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1878" + inkscape:window-height="1060" + id="namedview33" + showgrid="false" + inkscape:zoom="2.36" + inkscape:cx="-0.42372881" + inkscape:cy="50" + inkscape:window-x="-2" + inkscape:window-y="-3" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" /><switch + id="switch4" + transform="translate(6.1779661,6.1779661)"><foreignObject + requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" + x="0" + y="0" + width="1" + height="1" + id="foreignObject6" /><g + i:extraneous="self" + id="g8"><g + id="Слой_1"><g + id="g11"><path + d="M 39,68.1 C 23.9,68.1 11.7,55.2 11.7,39.3 11.7,23.4 23.9,10.5 39,10.5 c 15.1,0 27.3,12.9 27.3,28.8 0,15.9 -12.2,28.8 -27.3,28.8 z m 0,-52.6 c -12.3,0 -22.3,10.7 -22.3,23.8 0,13.1 10,23.8 22.3,23.8 12.3,0 22.3,-10.7 22.3,-23.8 0,-13.1 -10,-23.8 -22.3,-23.8 z" + id="path13" + inkscape:connector-curvature="0" /></g><g + id="g15"><path + d="M 2.8,89.7 C 2.5,89.7 2.2,89.6 1.9,89.5 0.6,89 0,87.5 0.5,86.3 3.6,78.5 8.9,72 15.8,67.3 l 1.5,-1 1.4,1.1 c 6.3,4.6 13.7,7.1 21.6,7.1 7.3,0 14.4,-2.2 20.4,-6.3 l 1.5,-1 1.4,1.1 c 6.3,4.6 11.1,10.9 14,18.1 0.5,1.3 -0.1,2.7 -1.4,3.2 -1.3,0.5 -2.7,-0.1 -3.2,-1.4 -2.3,-5.8 -6.1,-11 -10.9,-14.9 -6.5,4 -14,6.2 -21.7,6.2 -8.3,0 -16.2,-2.4 -23,-7 C 12,76.5 7.9,82 5.3,88.3 4.7,89.1 3.8,89.7 2.8,89.7 z" + id="path17" + inkscape:connector-curvature="0" /></g><g + id="g19"><path + d="M 81.6,37.5 H 74.5 C 73.7,37.5 73,36.8 73,36 c 0,-0.8 0.7,-1.5 1.5,-1.5 h 7.1 c 0.8,0 1.5,0.7 1.5,1.5 0,0.8 -0.7,1.5 -1.5,1.5 z" + id="path21" + inkscape:connector-curvature="0" /></g><g + id="g23"><path + d="m 79.3,31.9 h -2 c -2.7,0 -4.8,-2.2 -4.8,-4.8 V 22.4 C 68.9,20.3 67,17.1 67,13 67,6.4 72,1 78.1,1 c 6.1,0 11.1,5.4 11.1,12 0,3.8 -1.7,6.9 -5,9.1 v 5.1 c -0.1,2.5 -2.3,4.7 -4.9,4.7 z M 78,4.9 c -3.9,0 -7.1,3.6 -7.1,8 0,3 1.4,5 4.3,6.4 l 1.1,0.5 V 27 c 0,0.4 0.4,0.8 0.8,0.8 h 2 c 0.4,0 0.8,-0.4 0.8,-0.8 v -7.3 l 1,-0.6 c 2.7,-1.5 3.9,-3.4 3.9,-6.2 0.3,-4.4 -2.9,-8 -6.8,-8 z" + id="path25" + inkscape:connector-curvature="0" /></g></g><g + id="Слой_2" /><g + id="Слой_3" /></g></switch></svg>
\ No newline at end of file diff --git a/main/project/rawimages/noun_104277_cc.svg b/main/project/rawimages/noun_104277_cc.svg new file mode 100644 index 0000000..cf0efbb --- /dev/null +++ b/main/project/rawimages/noun_104277_cc.svg @@ -0,0 +1,26 @@ +<svg xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="4.5 -9.0 90.0 121.5" enable-background="new 0 0 90 90" xml:space="preserve" height="100px" width="100px"> +<switch> + <foreignObject requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" x="0" y="0" width="1" height="1"> + </foreignObject> + <g i:extraneous="self"> + <g id="Слой_1"> + <g> + <path d="M39,68.1c-15.1,0-27.3-12.9-27.3-28.8S23.9,10.5,39,10.5c15.1,0,27.3,12.9,27.3,28.8S54.1,68.1,39,68.1z M39,15.5 c-12.3,0-22.3,10.7-22.3,23.8c0,13.1,10,23.8,22.3,23.8c12.3,0,22.3-10.7,22.3-23.8C61.3,26.2,51.3,15.5,39,15.5z"/> + </g> + <g> + <path d="M2.8,89.7c-0.3,0-0.6-0.1-0.9-0.2c-1.3-0.5-1.9-2-1.4-3.2c3.1-7.8,8.4-14.3,15.3-19l1.5-1l1.4,1.1 c6.3,4.6,13.7,7.1,21.6,7.1c7.3,0,14.4-2.2,20.4-6.3l1.5-1l1.4,1.1c6.3,4.6,11.1,10.9,14,18.1c0.5,1.3-0.1,2.7-1.4,3.2 c-1.3,0.5-2.7-0.1-3.2-1.4c-2.3-5.8-6.1-11-10.9-14.9c-6.5,4-14,6.2-21.7,6.2c-8.3,0-16.2-2.4-23-7c-5.4,4-9.5,9.5-12.1,15.8 C4.7,89.1,3.8,89.7,2.8,89.7z"/> + </g> + <g> + <path d="M81.6,37.5h-7.1c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5h7.1c0.8,0,1.5,0.7,1.5,1.5S82.4,37.5,81.6,37.5z"/> + </g> + <g> + <path d="M79.3,31.9h-2c-2.7,0-4.8-2.2-4.8-4.8v-4.7c-3.6-2.1-5.5-5.3-5.5-9.4c0-6.6,5-12,11.1-12s11.1,5.4,11.1,12 c0,3.8-1.7,6.9-5,9.1v5.1C84.1,29.7,81.9,31.9,79.3,31.9z M78,4.9c-3.9,0-7.1,3.6-7.1,8c0,3,1.4,5,4.3,6.4l1.1,0.5v7.2 c0,0.4,0.4,0.8,0.8,0.8h2c0.4,0,0.8-0.4,0.8-0.8v-7.3l1-0.6c2.7-1.5,3.9-3.4,3.9-6.2C85.1,8.5,81.9,4.9,78,4.9z"/> + </g> + </g> + <g id="Слой_2"> + </g> + <g id="Слой_3"> + </g> + </g> +</switch> +<text x="0.0" y="105.75" font-size="4.5" font-weight="bold" font-family="Helvetica Neue, Helvetica, Arial-Unicode, Arial, Sans-serif" fill="#000000">Created by Artem Korotkikh</text><text x="0.0" y="110.25" font-size="4.5" font-weight="bold" font-family="Helvetica Neue, Helvetica, Arial-Unicode, Arial, Sans-serif" fill="#000000">from the Noun Project</text></svg>
\ No newline at end of file diff --git a/main/res/drawable-hdpi/ic_menu_hint.png b/main/res/drawable-hdpi/ic_menu_hint.png Binary files differnew file mode 100644 index 0000000..1b3c7ad --- /dev/null +++ b/main/res/drawable-hdpi/ic_menu_hint.png diff --git a/main/res/drawable-hdpi/ic_menu_mylocation_off.png b/main/res/drawable-hdpi/ic_menu_mylocation_off.png Binary files differnew file mode 100644 index 0000000..d3e962f --- /dev/null +++ b/main/res/drawable-hdpi/ic_menu_mylocation_off.png diff --git a/main/res/drawable-hdpi/star_half.png b/main/res/drawable-hdpi/star_half.png Binary files differdeleted file mode 100644 index 000208c..0000000 --- a/main/res/drawable-hdpi/star_half.png +++ /dev/null diff --git a/main/res/drawable-ldpi/ic_menu_barcode.png b/main/res/drawable-ldpi/ic_menu_barcode.png Binary files differdeleted file mode 100644 index 3329f45..0000000 --- a/main/res/drawable-ldpi/ic_menu_barcode.png +++ /dev/null diff --git a/main/res/drawable-ldpi/ic_menu_filter.png b/main/res/drawable-ldpi/ic_menu_filter.png Binary files differdeleted file mode 100644 index 11b728d..0000000 --- a/main/res/drawable-ldpi/ic_menu_filter.png +++ /dev/null diff --git a/main/res/drawable-ldpi/ic_menu_goto.png b/main/res/drawable-ldpi/ic_menu_goto.png Binary files differdeleted file mode 100644 index d15ea3d..0000000 --- a/main/res/drawable-ldpi/ic_menu_goto.png +++ /dev/null diff --git a/main/res/drawable-ldpi/ic_menu_shopping.png b/main/res/drawable-ldpi/ic_menu_shopping.png Binary files differdeleted file mode 100644 index e881d50..0000000 --- a/main/res/drawable-ldpi/ic_menu_shopping.png +++ /dev/null diff --git a/main/res/drawable-ldpi/ic_menu_trail.png b/main/res/drawable-ldpi/ic_menu_trail.png Binary files differdeleted file mode 100644 index 2911566..0000000 --- a/main/res/drawable-ldpi/ic_menu_trail.png +++ /dev/null diff --git a/main/res/drawable-ldpi/star_half.png b/main/res/drawable-ldpi/star_half.png Binary files differdeleted file mode 100644 index 97fa464..0000000 --- a/main/res/drawable-ldpi/star_half.png +++ /dev/null diff --git a/main/res/drawable-mdpi/ic_menu_hint.png b/main/res/drawable-mdpi/ic_menu_hint.png Binary files differnew file mode 100644 index 0000000..e9cfcd6 --- /dev/null +++ b/main/res/drawable-mdpi/ic_menu_hint.png diff --git a/main/res/drawable-mdpi/star_half.png b/main/res/drawable-mdpi/star_half.png Binary files differdeleted file mode 100644 index 1ea9152..0000000 --- a/main/res/drawable-mdpi/star_half.png +++ /dev/null diff --git a/main/res/drawable-xhdpi/ic_menu_hint.png b/main/res/drawable-xhdpi/ic_menu_hint.png Binary files differnew file mode 100644 index 0000000..0c39096 --- /dev/null +++ b/main/res/drawable-xhdpi/ic_menu_hint.png diff --git a/main/res/drawable-xxhdpi/ic_menu_hint.png b/main/res/drawable-xxhdpi/ic_menu_hint.png Binary files differnew file mode 100644 index 0000000..c0c2ce3 --- /dev/null +++ b/main/res/drawable-xxhdpi/ic_menu_hint.png diff --git a/main/res/drawable/star_rating.xml b/main/res/drawable/star_rating.xml new file mode 100644 index 0000000..0d8a8e2 --- /dev/null +++ b/main/res/drawable/star_rating.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+android:id/background" + android:drawable="@drawable/star_off" /> + <item android:id="@+android:id/secondaryProgress" + android:drawable="@drawable/star_off" /> + <item android:id="@+android:id/progress" + android:drawable="@drawable/star_on" /> +</layer-list>
\ No newline at end of file diff --git a/main/res/layout-land/coordinatesinput_dialog.xml b/main/res/layout-land/coordinatesinput_dialog.xml index 202f1d3..001582b 100644 --- a/main/res/layout-land/coordinatesinput_dialog.xml +++ b/main/res/layout-land/coordinatesinput_dialog.xml @@ -14,7 +14,8 @@ <Spinner android:id="@+id/spinnerCoordinateFormats" android:layout_width="fill_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + tools:listitem="@android:layout/simple_spinner_item" /> <TableLayout android:id="@+id/coordTable" @@ -156,6 +157,14 @@ android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/waypoint_cache_coordinates" /> + + <Button + android:id="@+id/clipboard" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/from_clipboard" + android:visibility="gone" /> </LinearLayout> <Button diff --git a/main/res/layout-v11/actionbar_maps.xml b/main/res/layout-v11/actionbar_maps.xml index 3e72717..ee77673 100644 --- a/main/res/layout-v11/actionbar_maps.xml +++ b/main/res/layout-v11/actionbar_maps.xml @@ -1,7 +1,53 @@ <?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + style="@style/action_bar" > - <!-- Empty layout, on 11+ we have a real action bar --> -<merge xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" android:layout_height="match_parent"> + <!-- Add the up chevron to the icon --> -</merge>
\ No newline at end of file + <ImageView + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:src="@drawable/abc_ic_ab_back_holo_dark" /> + + <ImageView + style="@style/action_bar_action" + android:layout_marginLeft="-13dp" + android:onClick="navigateUp" /> + + <View style="@style/action_bar_separator" /> + + <TextView + android:id="@+id/actionbar_title" + style="@style/action_bar_title" + tools:ignore="InconsistentLayout" /> + + <ProgressBar + android:id="@+id/actionbar_progress" + style="@style/action_bar_progress" + android:visibility="gone" + tools:ignore="InconsistentLayout" /> + + <View style="@style/action_bar_separator" /> + + <FrameLayout style="@style/action_bar_action" > + + <CheckBox + android:id="@+id/my_position" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="right" + android:button="@drawable/ic_menu_myposition" + android:checked="false" + tools:ignore="InconsistentLayout" /> + </FrameLayout> + + <View style="@style/action_bar_separator" /> + + <ImageView + android:id="@+id/overflowActionBar" + style="@style/action_bar_action" + android:longClickable="true" + android:src="@drawable/abc_ic_menu_moreoverflow_normal_holo_dark" /> + +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout-v14/actionbar_maps.xml b/main/res/layout-v14/actionbar_maps.xml new file mode 100644 index 0000000..7ee9b51 --- /dev/null +++ b/main/res/layout-v14/actionbar_maps.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> + + <!-- Empty layout, on 14+ we have a real and working action bar --> +<merge xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" android:layout_height="match_parent"> + +</merge>
\ No newline at end of file diff --git a/main/res/layout/about_changes_page.xml b/main/res/layout/about_changes_page.xml index 544d338..04b5ff3 100644 --- a/main/res/layout/about_changes_page.xml +++ b/main/res/layout/about_changes_page.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".AboutActivity$ChangeLogViewCreator" > <LinearLayout android:layout_width="fill_parent" @@ -35,6 +37,21 @@ android:textColor="?text_color" android:textColorLink="?text_color_link" android:textSize="12sp" /> + + <TextView + android:id="@+id/changelog_github" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="true" + android:text="@string/changelog_github" + android:textColor="?text_color_link" + android:textColorLink="?text_color_link" + android:textSize="12sp" /> </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/main/res/layout/about_contributors_page.xml b/main/res/layout/about_contributors_page.xml index 9a0955e..844cb34 100644 --- a/main/res/layout/about_contributors_page.xml +++ b/main/res/layout/about_contributors_page.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".AboutActivity$ContributorsViewCreator" > <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/about_help_page.xml b/main/res/layout/about_help_page.xml index 0439e22..ed64b92 100644 --- a/main/res/layout/about_help_page.xml +++ b/main/res/layout/about_help_page.xml @@ -1,110 +1,184 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".AboutActivity$HelpViewCreator" > - <LinearLayout - android:layout_width="fill_parent" + <TableLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical" > + android:paddingLeft="10dp" > - <TextView - android:id="@+id/faq" + <TableRow + android:id="@+id/tableRow1" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/faq" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/website" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/faq_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/faq" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/faq_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow2" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/website" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/facebook" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/website_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/website" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/website_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow3" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/facebook" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/twitter" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/facebook_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/facebook" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/facebook_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow4" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/twitter" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/support" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/twitter_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/twitter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/twitter_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow5" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/support" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - - <TextView - android:id="@+id/market" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/support_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/support" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/support_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + + <TableRow + android:id="@+id/tableRow6" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:layout_marginBottom="5dip" - android:layout_marginLeft="10dip" - android:layout_marginRight="10dip" - android:clickable="true" - android:focusable="true" - android:linksClickable="false" - android:text="@string/market" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textSize="14sp" /> - </LinearLayout> + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/market_title" + android:textColor="?text_color" + android:textSize="14sp" /> + + <TextView + android:id="@+id/market" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:clickable="true" + android:focusable="true" + android:linksClickable="false" + android:text="@string/market_link" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + </TableRow> + </TableLayout> </ScrollView>
\ No newline at end of file diff --git a/main/res/layout/about_license_page.xml b/main/res/layout/about_license_page.xml index b33f0f9..e91adf1 100644 --- a/main/res/layout/about_license_page.xml +++ b/main/res/layout/about_license_page.xml @@ -4,7 +4,8 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".AboutActivity$LicenseViewCreator" > <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/about_system_page.xml b/main/res/layout/about_system_page.xml new file mode 100644 index 0000000..0fd9624 --- /dev/null +++ b/main/res/layout/about_system_page.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:padding="4dip" + tools:context=".AboutActivity$SystemViewCreator" > + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + <Button android:id="@+id/copy" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/copy_to_clipboard" + android:layout_gravity="center_horizontal" + android:padding="12dp" /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left" + android:layout_margin="7dip" + android:linksClickable="true" + android:paddingLeft="3dip" + android:text="@string/about_system_include" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textSize="14sp" /> + + <TextView + android:id="@+id/system" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left" + android:layout_margin="7dip" + android:linksClickable="true" + android:paddingLeft="3dip" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:textIsSelectable="true" + android:textSize="12sp" /> + </LinearLayout> + +</ScrollView> diff --git a/main/res/layout/about_version_page.xml b/main/res/layout/about_version_page.xml index 80630e4..53f9927 100644 --- a/main/res/layout/about_version_page.xml +++ b/main/res/layout/about_version_page.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".AboutActivity$VersionViewCreator" > <LinearLayout android:layout_width="fill_parent" @@ -83,6 +85,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" + android:baselineAligned="false" android:gravity="center_horizontal" android:orientation="horizontal" > diff --git a/main/res/layout/addresslist_activity.xml b/main/res/layout/addresslist_activity.xml index 4fbe53c..57d13f2 100644 --- a/main/res/layout/addresslist_activity.xml +++ b/main/res/layout/addresslist_activity.xml @@ -3,7 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".AddressListActivity" > <ListView android:id="@android:id/list" diff --git a/main/res/layout/addresslist_item.xml b/main/res/layout/addresslist_item.xml index dac1768..aa04728 100644 --- a/main/res/layout/addresslist_item.xml +++ b/main/res/layout/addresslist_item.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/button_map" android:layout_width="fill_parent" android:layout_height="wrap_content" @@ -9,7 +10,8 @@ android:paddingBottom="7dip" android:paddingLeft="5dip" android:paddingRight="5dip" - android:paddingTop="7dip" > + android:paddingTop="7dip" + tools:context=".ui.AddressListAdapter" > <TextView android:id="@+id/label" diff --git a/main/res/layout/attribute_descriptions.xml b/main/res/layout/attribute_descriptions.xml deleted file mode 100644 index 1e67f72..0000000 --- a/main/res/layout/attribute_descriptions.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/attribute_descriptions" - android:layout_width="fill_parent" - android:layout_height="wrap_content" > - - <TextView - android:id="@+id/attribute_descriptions_textview" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:linksClickable="true" - android:textColor="?text_color" - android:textColorLink="?text_color_link" - android:textIsSelectable="false" - android:textSize="14sp" /> - -</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/attribute_image.xml b/main/res/layout/attribute_image.xml index f68aef4..75eff6a 100644 --- a/main/res/layout/attribute_image.xml +++ b/main/res/layout/attribute_image.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/attribute_images" android:layout_width="wrap_content" - android:layout_height="wrap_content" > + android:layout_height="wrap_content" + tools:context=".CacheDetailActivity$AttributeViewBuilder" > <ImageView android:id="@+id/attribute_image" diff --git a/main/res/layout/authorization_activity.xml b/main/res/layout/authorization_activity.xml index 2907286..6364ee2 100644 --- a/main/res/layout/authorization_activity.xml +++ b/main/res/layout/authorization_activity.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".network.OAuthAuthorizationActivity" > <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/cache_information_item.xml b/main/res/layout/cache_information_item.xml index 1b766e4..d213e56 100644 --- a/main/res/layout/cache_information_item.xml +++ b/main/res/layout/cache_information_item.xml @@ -34,17 +34,17 @@ android:textIsSelectable="false" android:textSize="14sp" /> - <LinearLayout + <RatingBar android:id="@+id/stars" + style="@style/cacheRatingBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" + android:layout_gravity="center_horizontal" android:layout_toRightOf="@+id/value" android:baselineAligned="false" android:gravity="center_vertical" - android:orientation="horizontal" - android:visibility="gone" > - </LinearLayout> + android:visibility="gone" /> <TextView android:id="@+id/addition" diff --git a/main/res/layout/cachedetail_activity.xml b/main/res/layout/cachedetail_activity.xml index d197bcd..b2e16a0 100644 --- a/main/res/layout/cachedetail_activity.xml +++ b/main/res/layout/cachedetail_activity.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="?background_color"
- android:orientation="vertical" >
+ android:orientation="vertical"
+ tools:context=".CacheDetailActivity" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
diff --git a/main/res/layout/cachedetail_description_page.xml b/main/res/layout/cachedetail_description_page.xml index dba6789..4fa342d 100644 --- a/main/res/layout/cachedetail_description_page.xml +++ b/main/res/layout/cachedetail_description_page.xml @@ -1,7 +1,9 @@ <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
+ android:layout_height="fill_parent"
+ tools:context=".CacheDetailActivity$DescriptionViewCreator" >
<LinearLayout
android:layout_width="fill_parent"
@@ -134,6 +136,7 @@ android:id="@+id/edit_personalnote"
style="@style/button_small"
android:text="@string/cache_personal_note_edit" />
+
<Button
android:id="@+id/upload_personalnote"
style="@style/button_small"
diff --git a/main/res/layout/cachedetail_details_page.xml b/main/res/layout/cachedetail_details_page.xml index 7b67846..7b48554 100644 --- a/main/res/layout/cachedetail_details_page.xml +++ b/main/res/layout/cachedetail_details_page.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:scrollbars="none" >
+ android:scrollbars="none"
+ tools:context=".CacheDetailActivity$DetailsViewCreator" >
<LinearLayout
android:layout_width="fill_parent"
@@ -25,23 +27,38 @@ android:id="@+id/attributes_box"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone" >
+ android:orientation="vertical" >
<View
style="@style/separator_horizontal"
android:layout_marginBottom="9dp"
android:layout_marginTop="9dp" />
- <!-- innerbox is only needed to define the paddings easily -->
+ <cgeo.geocaching.ui.WrappingGridView
+ android:id="@+id/attributes_grid"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:columnWidth="32dip"
+ android:horizontalSpacing="2dip"
+ android:numColumns="auto_fit"
+ android:paddingLeft="6dp"
+ android:paddingRight="6dp"
+ android:scrollbars="none"
+ android:stretchMode="none"
+ android:verticalSpacing="2dip" />
- <LinearLayout
- android:id="@+id/attributes_innerbox"
+ <TextView
+ android:id="@+id/attributes_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
+ android:layout_gravity="left"
+ android:linksClickable="true"
android:paddingLeft="6dp"
- android:paddingRight="6dp" />
+ android:paddingRight="6dp"
+ android:textColor="?text_color"
+ android:textColorLink="?text_color_link"
+ android:textIsSelectable="false"
+ android:textSize="14sp" />
</LinearLayout>
<!-- Offline box -->
diff --git a/main/res/layout/cachedetail_images_page.xml b/main/res/layout/cachedetail_images_page.xml index 2360dd0..cf26fe5 100644 --- a/main/res/layout/cachedetail_images_page.xml +++ b/main/res/layout/cachedetail_images_page.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
- android:padding="4dip" >
+ android:padding="4dip"
+ tools:context=".CacheDetailActivity$ImagesViewCreator" >
<LinearLayout
android:id="@+id/spoiler_list"
diff --git a/main/res/layout/cachedetail_inventory_page.xml b/main/res/layout/cachedetail_inventory_page.xml index a15cedd..c134a79 100644 --- a/main/res/layout/cachedetail_inventory_page.xml +++ b/main/res/layout/cachedetail_inventory_page.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="?background_color"
android:clipToPadding="false"
- android:scrollbarStyle="outsideOverlay" >
+ android:scrollbarStyle="outsideOverlay"
+ tools:context=".CacheDetailActivity$InventoryViewCreator" >
</ListView>
\ No newline at end of file diff --git a/main/res/layout/cachedetail_waypoints_footer.xml b/main/res/layout/cachedetail_waypoints_footer.xml index 58187c1..440363b 100644 --- a/main/res/layout/cachedetail_waypoints_footer.xml +++ b/main/res/layout/cachedetail_waypoints_footer.xml @@ -1,9 +1,10 @@ <?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/add_waypoint"
style="@style/button_full"
android:layout_margin="10dip"
- android:padding="10dip"
android:clickable="true"
- android:text="@string/cache_waypoints_add" />
-
+ android:padding="10dip"
+ android:text="@string/cache_waypoints_add"
+ tools:context=".CacheDetailActivity$WaypointsViewCreator" />
diff --git a/main/res/layout/cachedetail_waypoints_page.xml b/main/res/layout/cachedetail_waypoints_page.xml index 8111210..dbf896a 100644 --- a/main/res/layout/cachedetail_waypoints_page.xml +++ b/main/res/layout/cachedetail_waypoints_page.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="?background_color"
@@ -11,6 +12,7 @@ android:footerDividersEnabled="false"
android:headerDividersEnabled="false"
android:listSelector="?background_color"
- android:scrollbarStyle="outsideOverlay" >
+ android:scrollbarStyle="outsideOverlay"
+ tools:context=".CacheDetailActivity$WaypointsViewCreator" >
</ListView>
\ No newline at end of file diff --git a/main/res/layout/cachelist_spinneritem.xml b/main/res/layout/cachelist_spinneritem.xml index 58e070e..fce9b88 100644 --- a/main/res/layout/cachelist_spinneritem.xml +++ b/main/res/layout/cachelist_spinneritem.xml @@ -1,14 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> - <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" - android:orientation="vertical" android:layout_width="match_parent" + style="?attr/spinnerDropDownItemStyle" + android:layout_width="match_parent" android:layout_height="?attr/dropdownListPreferredItemHeight" - android:minHeight="?attr/dropdownListPreferredItemHeight" android:layout_gravity="left|center_vertical" - style="?attr/spinnerDropDownItemStyle" - > - + android:minHeight="?attr/dropdownListPreferredItemHeight" + android:orientation="vertical" + tools:context=".CacheListSpinnerAdapter" > <TextView android:id="@android:id/text1" diff --git a/main/res/layout/cacheslist_activity.xml b/main/res/layout/cacheslist_activity.xml index 561baa2..62d9861 100644 --- a/main/res/layout/cacheslist_activity.xml +++ b/main/res/layout/cacheslist_activity.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".CacheListActivity" > <include layout="@layout/filter_bar" /> @@ -33,6 +35,7 @@ android:fastScrollEnabled="true" android:padding="0dip" android:scrollbarStyle="outsideOverlay" - android:visibility="gone" /> + android:visibility="gone" + tools:listitem="@layout/cacheslist_item" /> </LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/cacheslist_footer.xml b/main/res/layout/cacheslist_footer.xml index ed2de18..ff323f4 100644 --- a/main/res/layout/cacheslist_footer.xml +++ b/main/res/layout/cacheslist_footer.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/more_caches" android:layout_width="fill_parent" android:layout_height="fill_parent" @@ -13,4 +14,5 @@ android:singleLine="true" android:text="@string/caches_no_cache" android:textColor="@color/just_white" - android:textSize="16sp" /> + android:textSize="16sp" + tools:context=".CacheListActivity" /> diff --git a/main/res/layout/cacheslist_item.xml b/main/res/layout/cacheslist_item.xml index 260b0d0..9c5ca28 100644 --- a/main/res/layout/cacheslist_item.xml +++ b/main/res/layout/cacheslist_item.xml @@ -5,7 +5,8 @@ android:id="@+id/one_cache" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:background="?background_color" > + android:background="?background_color" + tools:context=".ui.CacheListAdapter" > <!-- selection mode checkbox --> @@ -139,15 +140,23 @@ android:layout_marginBottom="1dip" android:layout_marginTop="1dip" > - <ImageView + <TextView android:id="@+id/inventory" android:layout_width="35dip" android:layout_height="22dip" android:layout_alignParentTop="true" android:layout_gravity="center_vertical|center_horizontal" android:background="?inventory" + android:drawableLeft="@drawable/trackable_all" + android:drawablePadding="-10sp" + android:gravity="center" android:scaleType="center" - android:src="@drawable/trackable_all" /> + android:singleLine="true" + android:text="" + android:textColor="?text_color" + android:textIsSelectable="false" + android:textSize="12sp" + android:textStyle="bold" /> <TextView android:id="@+id/favorite" diff --git a/main/res/layout/compass_activity.xml b/main/res/layout/compass_activity.xml index ca61cc3..f618d71 100644 --- a/main/res/layout/compass_activity.xml +++ b/main/res/layout/compass_activity.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".CompassActivity" > <LinearLayout android:id="@+id/info1" @@ -16,16 +18,20 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:text="@null" android:textColor="?text_color" - android:textSize="14sp" /> + android:textSize="14sp" + tools:text="Destination coordinates" /> <TextView android:id="@+id/cacheinfo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:text="@null" android:textColor="?text_color" - android:textSize="14sp" /> + android:textSize="14sp" + tools:text="Cache information (D/T/S)" /> <RelativeLayout android:layout_width="fill_parent" @@ -40,7 +46,8 @@ android:layout_marginLeft="3dip" android:text="@null" android:textColor="?text_color" - android:textSize="26sp" /> + android:textSize="26sp" + tools:text="123°" /> <TextView android:id="@+id/distance" @@ -51,7 +58,8 @@ android:layout_marginRight="3dip" android:text="@null" android:textColor="?text_color" - android:textSize="26sp" /> + android:textSize="26sp" + tools:text="123 km" /> </RelativeLayout> </LinearLayout> diff --git a/main/res/layout/coordinatesinput_dialog.xml b/main/res/layout/coordinatesinput_dialog.xml index 9b5cb8d..805d455 100644 --- a/main/res/layout/coordinatesinput_dialog.xml +++ b/main/res/layout/coordinatesinput_dialog.xml @@ -3,7 +3,8 @@ android:id="@+id/scroller" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:fillViewport="true" > + android:fillViewport="true" + tools:context=".ui.dialog.CoordinatesInputDialog" > <LinearLayout android:id="@+id/scroller_child" @@ -14,7 +15,8 @@ <Spinner android:id="@+id/spinnerCoordinateFormats" android:layout_width="fill_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + tools:listitem="@android:layout/simple_spinner_item" /> <TableLayout android:id="@+id/coordTable" @@ -151,6 +153,14 @@ android:text="@string/waypoint_cache_coordinates" /> <Button + android:id="@+id/clipboard" + style="@style/button_full" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/from_clipboard" + android:visibility="gone" /> + + <Button android:id="@+id/done" style="@style/button_full" android:layout_width="fill_parent" diff --git a/main/res/layout/editwaypoint_activity.xml b/main/res/layout/editwaypoint_activity.xml index c21e25d..c11ffea 100644 --- a/main/res/layout/editwaypoint_activity.xml +++ b/main/res/layout/editwaypoint_activity.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".EditWaypointActivity" > <LinearLayout android:layout_width="fill_parent" @@ -46,19 +48,22 @@ android:id="@+id/distanceUnit" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:entries="@array/distance_units" /> - </LinearLayout> + android:entries="@array/distance_units" + tools:listitem="@android:layout/simple_spinner_item" /> - <AutoCompleteTextView - android:id="@+id/name" - style="@style/edittext_full" - android:hint="@string/waypoint_name" /> + </LinearLayout> <Spinner android:id="@+id/type" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:visibility="gone" /> + android:visibility="gone" + tools:listitem="@android:layout/simple_spinner_item" /> + + <AutoCompleteTextView + android:id="@+id/name" + style="@style/edittext_full" + android:hint="@string/waypoint_name" /> <EditText android:id="@+id/note" diff --git a/main/res/layout/fieldnote_export_dialog.xml b/main/res/layout/fieldnote_export_dialog.xml index 9859b0f..c76225c 100644 --- a/main/res/layout/fieldnote_export_dialog.xml +++ b/main/res/layout/fieldnote_export_dialog.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:padding="3dip" >
+ android:padding="3dip"
+ tools:context=".export.FieldnoteExport" >
<TextView
android:layout_width="wrap_content"
diff --git a/main/res/layout/filter_activity.xml b/main/res/layout/filter_activity.xml new file mode 100644 index 0000000..8858452 --- /dev/null +++ b/main/res/layout/filter_activity.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + tools:context=".filter.FilterActivity" > + + <ScrollView + android:id="@+id/scrollView" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + + <LinearLayout + android:id="@+id/filters" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + </LinearLayout> + </ScrollView> + + + <ExpandableListView + android:id="@+id/filterList" + android:layout_width="match_parent" + android:layout_height="fill_parent" > + </ExpandableListView> + +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/filter_list_child.xml b/main/res/layout/filter_list_child.xml new file mode 100644 index 0000000..7978269 --- /dev/null +++ b/main/res/layout/filter_list_child.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="start" + android:layout_marginTop="6dip" + android:textAlignment="viewStart" + android:textAppearance="?android:attr/textAppearanceLarge" /> diff --git a/main/res/layout/fragment_edit_note.xml b/main/res/layout/fragment_edit_note.xml index 1e9fbf9..893dc31 100644 --- a/main/res/layout/fragment_edit_note.xml +++ b/main/res/layout/fragment_edit_note.xml @@ -1,9 +1,11 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/edit_note" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".ui.EditNoteDialog" > <EditText android:id="@+id/note" diff --git a/main/res/layout/gcvote_dialog.xml b/main/res/layout/gcvote_dialog.xml new file mode 100644 index 0000000..221a8f5 --- /dev/null +++ b/main/res/layout/gcvote_dialog.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dip" + android:orientation="vertical" > + + <include layout="@layout/gcvote_rating_bar" /> + +</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/gcvote_rating_bar.xml b/main/res/layout/gcvote_rating_bar.xml new file mode 100644 index 0000000..87d4ef5 --- /dev/null +++ b/main/res/layout/gcvote_rating_bar.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<merge xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" > + + <RatingBar + android:id="@+id/gcvoteRating" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:max="5" + android:numStars="5" + android:stepSize="0.5" + android:visibility="gone" /> + + <TextView + android:id="@+id/gcvoteLabel" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:padding="10dip" + android:text="@string/log_no_rating" + android:textColor="?text_color" + android:textSize="12sp" + android:visibility="gone" /> + +</merge> diff --git a/main/res/layout/gpx.xml b/main/res/layout/gpx.xml index 4367f82..fc743bd 100644 --- a/main/res/layout/gpx.xml +++ b/main/res/layout/gpx.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:orientation="vertical" > + android:orientation="vertical" + android:background="?background_color" + tools:context=".files.AbstractFileListActivity" > <Button android:id="@+id/select_dir" diff --git a/main/res/layout/gpx_export_dialog.xml b/main/res/layout/gpx_export_dialog.xml index 9c97848..02e9134 100644 --- a/main/res/layout/gpx_export_dialog.xml +++ b/main/res/layout/gpx_export_dialog.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:padding="3dip" >
+ android:padding="3dip"
+ tools:context=".export.GpxExport" >
<TextView
android:id="@id/info"
diff --git a/main/res/layout/gpx_item.xml b/main/res/layout/gpx_item.xml index f0a0647..372bb9a 100644 --- a/main/res/layout/gpx_item.xml +++ b/main/res/layout/gpx_item.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/button_map" android:layout_width="fill_parent" android:layout_height="wrap_content" @@ -9,7 +10,8 @@ android:paddingBottom="7dip" android:paddingLeft="5dip" android:paddingRight="5dip" - android:paddingTop="7dip" > + android:paddingTop="7dip" + tools:context=".ui.GPXListAdapter" > <TextView android:id="@+id/filepath" diff --git a/main/res/layout/grid_image.xml b/main/res/layout/grid_image.xml new file mode 100644 index 0000000..4e145f5 --- /dev/null +++ b/main/res/layout/grid_image.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<ImageView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="0dp" + android:scaleType="fitCenter" + android:src="@drawable/type_traditional" + tools:context=".filter.FilterActivity" > + +</ImageView>
\ No newline at end of file diff --git a/main/res/layout/image_item.xml b/main/res/layout/image_item.xml index 3478444..5eae256 100644 --- a/main/res/layout/image_item.xml +++ b/main/res/layout/image_item.xml @@ -1,7 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/map_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:gravity="center" /> + android:gravity="center" + tools:context=".ui.ImagesList" /> diff --git a/main/res/layout/images_activity.xml b/main/res/layout/images_activity.xml index 861fa7e..d32e9e5 100644 --- a/main/res/layout/images_activity.xml +++ b/main/res/layout/images_activity.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".ImagesActivity" > <include layout="@layout/cachedetail_images_page" /> diff --git a/main/res/layout/images_gridview.xml b/main/res/layout/images_gridview.xml new file mode 100644 index 0000000..b3993af --- /dev/null +++ b/main/res/layout/images_gridview.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<GridView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/gridView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:columnWidth="80dp" + android:gravity="center" + android:horizontalSpacing="0dp" + android:numColumns="auto_fit" + android:stretchMode="spacingWidth" + android:verticalSpacing="0dp" + tools:listitem="@layout/grid_image" > + +</GridView> diff --git a/main/res/layout/imageselect_activity.xml b/main/res/layout/imageselect_activity.xml index 690baa2..59c90a4 100644 --- a/main/res/layout/imageselect_activity.xml +++ b/main/res/layout/imageselect_activity.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".ImageSelectActivity" > <LinearLayout android:layout_width="fill_parent" @@ -24,6 +26,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" + android:baselineAligned="false" android:orientation="horizontal" > <Button @@ -76,7 +79,8 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:entries="@array/log_image_scales" - android:prompt="@string/log_image_scale" /> + android:prompt="@string/log_image_scale" + tools:listitem="@android:layout/simple_spinner_item" /> <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/internal_browser.xml b/main/res/layout/internal_browser.xml index 1e09ee0..cf38076 100644 --- a/main/res/layout/internal_browser.xml +++ b/main/res/layout/internal_browser.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> - <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent"> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:context=".activity.SimpleWebviewActivity" > <WebView - android:id="@+id/webview" - android:layout_width="match_parent" - android:layout_height="match_parent" /> + android:id="@+id/webview" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/livemapinfo.xml b/main/res/layout/livemapinfo.xml index 889febc..564ed00 100644 --- a/main/res/layout/livemapinfo.xml +++ b/main/res/layout/livemapinfo.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/live_map_scroll" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".ui.dialog.LiveMapInfoDialogBuilder" > <LinearLayout android:layout_width="fill_parent" @@ -18,7 +20,6 @@ android:text="@string/live_map_notification" android:textColor="?text_color" android:textSize="14sp" /> - </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/main/res/layout/logcache_activity.xml b/main/res/layout/logcache_activity.xml index b01ea74..2e966d1 100644 --- a/main/res/layout/logcache_activity.xml +++ b/main/res/layout/logcache_activity.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" android:orientation="vertical" - android:padding="4dip" xmlns:tools="http://schemas.android.com/tools"> + android:padding="4dip" + tools:context=".LogCacheActivity" > <LinearLayout android:layout_width="fill_parent" @@ -20,6 +22,7 @@ <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" + android:baselineAligned="false" android:orientation="horizontal" > <Button @@ -69,29 +72,9 @@ android:inputType="text" android:singleLine="true" tools:ignore="TextFields" /> - </LinearLayout> - <RatingBar - android:id="@+id/gcvoteRating" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:max="5" - android:numStars="5" - android:stepSize="0.5" - android:visibility="gone" /> - - <TextView - android:id="@+id/gcvoteLabel" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:gravity="center_horizontal" - android:padding="10dip" - android:text="@string/log_no_rating" - android:textColor="?text_color" - android:textSize="12sp" - android:visibility="gone" /> + <include layout="@layout/gcvote_rating_bar" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <LinearLayout android:id="@+id/tweet_box" diff --git a/main/res/layout/logcache_trackable_item.xml b/main/res/layout/logcache_trackable_item.xml index 1eab116..72082ac 100644 --- a/main/res/layout/logcache_trackable_item.xml +++ b/main/res/layout/logcache_trackable_item.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dip" android:orientation="horizontal" android:paddingBottom="10dip" android:paddingLeft="10dip" - android:paddingRight="10dip" > + android:paddingRight="10dip" + tools:context=".LogCacheActivity" > <LinearLayout android:id="@+id/info" diff --git a/main/res/layout/logs_item.xml b/main/res/layout/logs_item.xml index 6ce20bb..b362d9e 100644 --- a/main/res/layout/logs_item.xml +++ b/main/res/layout/logs_item.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="3dip" - android:paddingTop="3dip" > + android:paddingTop="3dip" + tools:context=".ui.logs.LogsViewCreator$1" > <TextView android:id="@+id/author" diff --git a/main/res/layout/logs_page.xml b/main/res/layout/logs_page.xml index 11f7855..e168be5 100644 --- a/main/res/layout/logs_page.xml +++ b/main/res/layout/logs_page.xml @@ -12,6 +12,7 @@ android:headerDividersEnabled="false"
android:listSelector="?background_color"
android:scrollbarStyle="outsideOverlay"
+ tools:context=".ui.logs.LogsViewCreator"
tools:listitem="@layout/logs_item" >
</ListView>
\ No newline at end of file diff --git a/main/res/layout/logtrackable_activity.xml b/main/res/layout/logtrackable_activity.xml index 2a901ea..66fa016 100644 --- a/main/res/layout/logtrackable_activity.xml +++ b/main/res/layout/logtrackable_activity.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".LogTrackableActivity" > <LinearLayout android:layout_width="fill_parent" @@ -14,6 +16,7 @@ <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" + android:baselineAligned="false" android:orientation="horizontal" > <Button diff --git a/main/res/layout/main_activity.xml b/main/res/layout/main_activity.xml index d2bd025..474565f 100644 --- a/main/res/layout/main_activity.xml +++ b/main/res/layout/main_activity.xml @@ -4,7 +4,8 @@ android:id="@+id/mainscreen" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:layout_gravity="center" > + android:layout_gravity="center" + tools:context=".MainActivity" > <fragment android:id="@+id/status" diff --git a/main/res/layout/main_activity_connectorstatus.xml b/main/res/layout/main_activity_connectorstatus.xml index 33c4d79..6c334aa 100644 --- a/main/res/layout/main_activity_connectorstatus.xml +++ b/main/res/layout/main_activity_connectorstatus.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" style="@style/location_current" - android:text="@string/init_login_popup_working" /> + android:text="@string/init_login_popup_working" + tools:context=".MainActivity$1" /> diff --git a/main/res/layout/map_google.xml b/main/res/layout/map_google.xml index 85f550a..85fee7a 100644 --- a/main/res/layout/map_google.xml +++ b/main/res/layout/map_google.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:orientation="vertical" > - - + android:orientation="vertical" + tools:context=".maps.google.v1.GoogleMapProvider" > <include layout="@layout/actionbar_maps" /> diff --git a/main/res/layout/map_mapsforge.xml b/main/res/layout/map_mapsforge.xml index c44a3ee..a559545 100644 --- a/main/res/layout/map_mapsforge.xml +++ b/main/res/layout/map_mapsforge.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".maps.mapsforge.MapsforgeMapProvider" > <include layout="@layout/actionbar_maps" /> diff --git a/main/res/layout/map_mapsforge_old.xml b/main/res/layout/map_mapsforge_old.xml deleted file mode 100644 index daa5f74..0000000 --- a/main/res/layout/map_mapsforge_old.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" > - - <include layout="@layout/actionbar_maps" /> - - <include layout="@layout/filter_bar" /> - - <RelativeLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" > - - <TextView - android:id="@+id/number" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="5dip" - android:background="@drawable/icon_bcg" - android:ellipsize="marquee" - android:gravity="center_horizontal" - android:lines="1" - android:paddingLeft="5dip" - android:paddingRight="5dip" - android:scrollHorizontally="true" - android:singleLine="true" - android:textColor="@color/text_icon" - android:textSize="12sp" - android:visibility="gone" /> - - <view - android:id="@+id/mfmap_old" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - class="cgeo.geocaching.maps.mapsforge.v024.MapsforgeMapView024" - android:clickable="true" - android:enabled="true" - android:keepScreenOn="true" /> - </RelativeLayout> - -</LinearLayout>
\ No newline at end of file diff --git a/main/res/layout/mapfile_item.xml b/main/res/layout/mapfile_item.xml index c665894..dd17f69 100644 --- a/main/res/layout/mapfile_item.xml +++ b/main/res/layout/mapfile_item.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/mapfile_item" android:layout_width="fill_parent" android:layout_height="wrap_content" @@ -9,7 +10,8 @@ android:paddingBottom="7dip" android:paddingLeft="5dip" android:paddingRight="5dip" - android:paddingTop="7dip" > + android:paddingTop="7dip" + tools:context=".ui.FileSelectionListAdapter" > <TextView android:id="@+id/mapfilepath" diff --git a/main/res/layout/navigateanypoint_activity.xml b/main/res/layout/navigateanypoint_activity.xml index 3305d56..caec2f4 100644 --- a/main/res/layout/navigateanypoint_activity.xml +++ b/main/res/layout/navigateanypoint_activity.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".NavigateAnyPointActivity" > <ListView android:id="@+id/historyList" diff --git a/main/res/layout/navigateanypoint_header.xml b/main/res/layout/navigateanypoint_header.xml index caf2e48..a52f55e 100644 --- a/main/res/layout/navigateanypoint_header.xml +++ b/main/res/layout/navigateanypoint_header.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:weightSum="1" > + android:weightSum="1" + tools:context=".NavigateAnyPointActivity" > <RelativeLayout style="@style/separator_horizontal_layout" > @@ -61,7 +63,9 @@ android:id="@+id/distanceUnit" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:entries="@array/distance_units" /> + android:entries="@array/distance_units" + tools:listitem="@android:layout/simple_spinner_item" /> + </LinearLayout> <RelativeLayout style="@style/separator_horizontal_layout" > diff --git a/main/res/layout/popup.xml b/main/res/layout/popup.xml index de94d18..436c7d8 100644 --- a/main/res/layout/popup.xml +++ b/main/res/layout/popup.xml @@ -5,7 +5,7 @@ android:layout_height="fill_parent" android:background="?background_color_transparent" android:orientation="vertical" - tools:context=".CachePopup"> + tools:context=".CachePopupFragment" > <include layout="@layout/actionbar_popup" /> <ScrollView diff --git a/main/res/layout/preference_info_icon.xml b/main/res/layout/preference_info_icon.xml index 4de0a15..597e400 100644 --- a/main/res/layout/preference_info_icon.xml +++ b/main/res/layout/preference_info_icon.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent" - android:src="?attr/settings_info_icon" /> + android:layout_height="match_parent" + android:src="?attr/settings_info_icon" + tools:context=".settings.InfoPreference" /> diff --git a/main/res/layout/recaptcha_dialog.xml b/main/res/layout/recaptcha_dialog.xml index 66ad4ef..16e9bb8 100644 --- a/main/res/layout/recaptcha_dialog.xml +++ b/main/res/layout/recaptcha_dialog.xml @@ -1,12 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".connector.gc.RecaptchaHandler" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" + android:baselineAligned="false" android:gravity="center_horizontal" android:orientation="horizontal" > @@ -27,7 +30,6 @@ android:layout_gravity="center_vertical" android:scaleType="centerInside" android:src="@drawable/ic_menu_refresh" /> - </LinearLayout> <EditText diff --git a/main/res/layout/search_activity.xml b/main/res/layout/search_activity.xml index 894c461..902c707 100644 --- a/main/res/layout/search_activity.xml +++ b/main/res/layout/search_activity.xml @@ -5,7 +5,8 @@ android:layout_height="fill_parent" android:background="?background_color" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".SearchActivity" > <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/simple_dir_chooser.xml b/main/res/layout/simple_dir_chooser.xml index 167b2ec..ca7c6c8 100644 --- a/main/res/layout/simple_dir_chooser.xml +++ b/main/res/layout/simple_dir_chooser.xml @@ -4,7 +4,8 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".files.SimpleDirChooser" > <LinearLayout android:id="@+id/headerLayout" @@ -39,6 +40,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" + android:baselineAligned="false" android:orientation="horizontal" android:paddingTop="10dip" > diff --git a/main/res/layout/simple_dir_item.xml b/main/res/layout/simple_dir_item.xml index e268943..2abce4c 100644 --- a/main/res/layout/simple_dir_item.xml +++ b/main/res/layout/simple_dir_item.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" - android:orientation="horizontal" > + android:orientation="horizontal" + tools:context=".files.SimpleDirChooser" > <CheckBox android:id="@+id/CheckBox" diff --git a/main/res/layout/simple_way_point.xml b/main/res/layout/simple_way_point.xml index 88f76e7..333bb9d 100644 --- a/main/res/layout/simple_way_point.xml +++ b/main/res/layout/simple_way_point.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/linearLayout1" android:layout_width="wrap_content" - android:layout_height="wrap_content" > + android:layout_height="wrap_content" + tools:context=".NavigateAnyPointActivity$DestinationHistoryAdapter" > <ImageView android:id="@+id/imageView1" diff --git a/main/res/layout/star_image.xml b/main/res/layout/star_image.xml deleted file mode 100644 index 919fedb..0000000 --- a/main/res/layout/star_image.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<ImageView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="12dip" - android:layout_height="12dip" - android:layout_gravity="center" - android:layout_margin="1dip" - android:gravity="center" - android:scaleType="fitXY" - android:src="@drawable/star_off" /> diff --git a/main/res/layout/staticmaps_activity.xml b/main/res/layout/staticmaps_activity.xml index c8806b4..3ca336e 100644 --- a/main/res/layout/staticmaps_activity.xml +++ b/main/res/layout/staticmaps_activity.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".StaticMapsActivity" > <LinearLayout android:id="@+id/maps_list" diff --git a/main/res/layout/staticmaps_activity_item.xml b/main/res/layout/staticmaps_activity_item.xml index 6b76192..8600246 100644 --- a/main/res/layout/staticmaps_activity_item.xml +++ b/main/res/layout/staticmaps_activity_item.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/map_image" android:layout_width="fill_parent" android:layout_height="wrap_content" @@ -7,4 +8,5 @@ android:layout_marginBottom="10dip" android:gravity="center" android:padding="3dip" - android:scaleType="fitCenter" /> + android:scaleType="fitCenter" + tools:context=".StaticMapsActivity" /> diff --git a/main/res/layout/status.xml b/main/res/layout/status.xml index ef2a57a..76f9a8d 100644 --- a/main/res/layout/status.xml +++ b/main/res/layout/status.xml @@ -1,10 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/status" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/helper_bcg" - android:visibility="invisible" > + android:visibility="invisible" + tools:context=".StatusFragment" > <ImageView android:id="@+id/status_icon" diff --git a/main/res/layout/template_preference_dialog.xml b/main/res/layout/template_preference_dialog.xml index c5fc548..343cc5f 100644 --- a/main/res/layout/template_preference_dialog.xml +++ b/main/res/layout/template_preference_dialog.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:padding="8dp" > + android:padding="8dp" + tools:context=".settings.TemplateTextPreference" > <EditText android:id="@+id/signature_dialog_text" diff --git a/main/res/layout/trackable_details_view.xml b/main/res/layout/trackable_details_view.xml index 07f4e4e..e2c162e 100644 --- a/main/res/layout/trackable_details_view.xml +++ b/main/res/layout/trackable_details_view.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:padding="4dip" > + android:padding="4dip" + tools:context=".TrackableActivity$DetailsViewCreator" > <LinearLayout android:layout_width="fill_parent" diff --git a/main/res/layout/trackable_image.xml b/main/res/layout/trackable_image.xml index 89955bc..8a55cb7 100644 --- a/main/res/layout/trackable_image.xml +++ b/main/res/layout/trackable_image.xml @@ -1,9 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/trackable_image" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginBottom="3dip" android:gravity="center" - android:scaleType="center" /> + android:scaleType="center" + tools:context=".TrackableActivity$DetailsViewCreator" /> diff --git a/main/res/layout/usefulapps_activity.xml b/main/res/layout/usefulapps_activity.xml index 7abb212..8ecea23 100644 --- a/main/res/layout/usefulapps_activity.xml +++ b/main/res/layout/usefulapps_activity.xml @@ -4,7 +4,8 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".UsefulAppsActivity" > <ListView android:id="@+id/apps_list" diff --git a/main/res/layout/usefulapps_item.xml b/main/res/layout/usefulapps_item.xml index 70e7baf..1207ef7 100644 --- a/main/res/layout/usefulapps_item.xml +++ b/main/res/layout/usefulapps_item.xml @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/app_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginBottom="10dip" android:descendantFocusability="blocksDescendants" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".UsefulAppsActivity" > <RelativeLayout style="@style/separator_horizontal_layout" > @@ -23,6 +25,7 @@ android:layout_marginBottom="5dip" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" + android:baselineAligned="false" android:orientation="horizontal" > <ImageView diff --git a/main/res/layout/waypoint_item.xml b/main/res/layout/waypoint_item.xml index 4148dab..7b3c33a 100644 --- a/main/res/layout/waypoint_item.xml +++ b/main/res/layout/waypoint_item.xml @@ -8,7 +8,8 @@ android:descendantFocusability="blocksDescendants" android:longClickable="true" android:orientation="vertical" - android:paddingTop="9dp" > + android:paddingTop="9dp" + tools:context=".CacheDetailActivity$WaypointsViewCreator$1" > <RelativeLayout android:layout_width="fill_parent" @@ -97,4 +98,4 @@ style="@style/separator_horizontal" android:layout_marginTop="9dp" /> -</LinearLayout>
\ No newline at end of file +</LinearLayout> diff --git a/main/res/layout/waypoint_popup.xml b/main/res/layout/waypoint_popup.xml index 287fc3a..9a566ee 100644 --- a/main/res/layout/waypoint_popup.xml +++ b/main/res/layout/waypoint_popup.xml @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?background_color_transparent" - android:orientation="vertical" > + android:orientation="vertical" + tools:context=".WaypointPopupFragment" > - <include layout="@layout/actionbar_popup" /> + <include layout="@layout/actionbar_popup" /> <ScrollView android:id="@+id/details_list_box" diff --git a/main/res/menu/abstract_logging_activity.xml b/main/res/menu/abstract_logging_activity.xml index aeb6720..9c91399 100644 --- a/main/res/menu/abstract_logging_activity.xml +++ b/main/res/menu/abstract_logging_activity.xml @@ -32,6 +32,11 @@ <menu /> <!-- filled dynamically --> </item> <item + android:id="@+id/menu_repeat_last" + android:title="@string/log_repeat" + app:showAsAction="ifRoom|withText"> + </item> + <item android:id="@+id/save" android:icon="@drawable/ic_menu_save" android:title="@string/log_save" diff --git a/main/res/menu/cache_list_context.xml b/main/res/menu/cache_list_context.xml index c086709..86fd6f6 100644 --- a/main/res/menu/cache_list_context.xml +++ b/main/res/menu/cache_list_context.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_default_navigation" @@ -21,37 +21,37 @@ <item android:id="@+id/menu_log_visit_offline" android:icon="@drawable/ic_menu_edit" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_menu_visit_offline"> + android:title="@string/cache_menu_visit_offline" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_log_visit" android:icon="@drawable/ic_menu_edit" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_menu_visit"> + android:title="@string/cache_menu_visit" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_drop_cache" - app:showAsAction="ifRoom|withText" android:icon="@drawable/ic_menu_delete" - android:title="@string/cache_offline_drop"> + android:title="@string/cache_offline_drop" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_move_to_list" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_menu_move_list"> + android:title="@string/cache_menu_move_list" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_refresh" - app:showAsAction="ifRoom|withText" android:icon="@drawable/ic_menu_refresh" - android:title="@string/cache_menu_refresh"> + android:title="@string/cache_menu_refresh" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_store_cache" - app:showAsAction="ifRoom|withText" android:icon="@drawable/ic_menu_save" - android:title="@string/cache_offline_store"> + android:title="@string/cache_offline_store" + app:showAsAction="ifRoom|withText"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/cache_list_options.xml b/main/res/menu/cache_list_options.xml index 7c933c0..19a6882 100644 --- a/main/res/menu/cache_list_options.xml +++ b/main/res/menu/cache_list_options.xml @@ -53,12 +53,12 @@ android:visible="false"> </item> <item - android:id="@+id/submenu_cache_list_app" + android:id="@+id/menu_cache_list_app_provider" + android:actionProviderClass="cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider" android:icon="@drawable/ic_menu_goto" android:title="@string/caches_on_map" - android:visible="false"> - <menu> - </menu> + android:visible="false" + app:actionProviderClass="cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider"> </item> <item android:id="@+id/menu_create_list" @@ -108,15 +108,18 @@ </item> <item android:id="@+id/menu_delete_events" - android:title="@string/caches_delete_events"> + android:title="@string/caches_delete_events" + android:visible="false"> </item> <item android:id="@+id/menu_clear_offline_logs" - android:title="@string/caches_clear_offlinelogs"> + android:title="@string/caches_clear_offlinelogs" + android:visible="false"> </item> <item android:id="@+id/menu_remove_from_history" - android:title="@string/cache_clear_history"> + android:title="@string/cache_clear_history" + android:visible="false"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/cache_options.xml b/main/res/menu/cache_options.xml index 20ee9cd..f6ac51c 100644 --- a/main/res/menu/cache_options.xml +++ b/main/res/menu/cache_options.xml @@ -20,18 +20,21 @@ android:id="@+id/menu_log_visit_offline" android:icon="@drawable/ic_menu_edit" android:title="@string/cache_menu_visit_offline" + android:visible="false" app:showAsAction="ifRoom"> </item> <item android:id="@+id/menu_log_visit" android:icon="@drawable/ic_menu_edit" android:title="@string/cache_menu_visit" + android:visible="false" app:showAsAction="ifRoom"> </item> <item android:id="@+id/menu_calendar" android:icon="@drawable/ic_menu_my_calendar" android:title="@string/cache_menu_event" + android:visible="false" app:showAsAction="ifRoom"> </item> <item @@ -68,11 +71,29 @@ app:showAsAction="ifRoom"> </item> <item + android:id="@+id/menu_gcvote" + android:title="@string/cache_menu_vote" + android:visible="false" + app:showAsAction="ifRoom"> + </item> + <item android:id="@+id/menu_share" android:icon="@drawable/ic_menu_share" android:title="@string/cache_menu_share" app:actionProviderClass="android.support.v7.widget.ShareActionProvider" app:showAsAction="ifRoom"> </item> - + <item + android:id="@+id/menu_checker" + android:title="@string/cache_menu_checker" + android:visible="false" + app:showAsAction="ifRoom"> + </item> + <item + android:id="@+id/menu_ignore" + android:title="@string/cache_menu_ignore" + android:visible="false" + app:showAsAction="ifRoom"> + </item> + </menu>
\ No newline at end of file diff --git a/main/res/menu/compass_activity_options.xml b/main/res/menu/compass_activity_options.xml index 30861dd..742ebad 100644 --- a/main/res/menu/compass_activity_options.xml +++ b/main/res/menu/compass_activity_options.xml @@ -3,6 +3,12 @@ xmlns:app="http://schemas.android.com/apk/res-auto" > <item + android:id="@+id/menu_hint" + android:icon="@drawable/ic_menu_hint" + android:title="@string/cache_hint" + app:showAsAction="ifRoom|withText"> + </item> + <item android:id="@+id/menu_map" android:icon="@drawable/ic_menu_mapmode" android:title="@string/caches_on_map" @@ -24,9 +30,18 @@ <item android:id="@+id/menu_select_destination" android:icon="@drawable/ic_menu_myplaces" + android:orderInCategory="999" android:title="@string/destination_select" + android:visible="false" app:showAsAction="ifRoom|withText"> - <menu /> <!-- filled dynamically --> + <menu> + <item + android:id="@+id/menu_compass_cache" + android:orderInCategory="999" + android:title="@string/cache" + android:visible="false"> + </item> + </menu> </item> <item android:id="@+id/menu_compass_sensor" @@ -43,7 +58,7 @@ android:id="@+id/menu_compass_sensor_magnetic" android:title="@string/use_compass"> </item> - </group> + </group> </menu> </item> diff --git a/main/res/menu/details_context.xml b/main/res/menu/details_context.xml index 0bfb1a5..12afc22 100644 --- a/main/res/menu/details_context.xml +++ b/main/res/menu/details_context.xml @@ -10,8 +10,8 @@ </item> <item android:id="@+id/menu_cache_share_field" - android:title="@string/cache_share_field" android:icon="@drawable/ic_menu_share" + android:title="@string/cache_share_field" app:showAsAction="ifRoom"> </item> <item diff --git a/main/res/menu/filter_options.xml b/main/res/menu/filter_options.xml new file mode 100644 index 0000000..60733a6 --- /dev/null +++ b/main/res/menu/filter_options.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" > + + <item + android:id="@+id/menu_reset_filter" + android:icon="@drawable/ic_menu_delete" + android:title="@string/caches_filter_clear" + app:showAsAction="ifRoom|withText"> + </item> + +</menu>
\ No newline at end of file diff --git a/main/res/menu/images_list_context.xml b/main/res/menu/images_list_context.xml index 8d3869b..8f3d6b6 100644 --- a/main/res/menu/images_list_context.xml +++ b/main/res/menu/images_list_context.xml @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/image_open_file" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_image_open_file"> + android:title="@string/cache_image_open_file" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/image_open_browser" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_image_open_browser"> + android:title="@string/cache_image_open_browser" + app:showAsAction="ifRoom|withText"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/logging_ui.xml b/main/res/menu/logging_ui.xml index 921b350..7c41c6f 100644 --- a/main/res/menu/logging_ui.xml +++ b/main/res/menu/logging_ui.xml @@ -1,18 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_log_visit_offline" android:icon="@drawable/ic_menu_edit" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_menu_visit_offline"> + android:title="@string/cache_menu_visit_offline" + android:visible="false" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_log_visit" android:icon="@drawable/ic_menu_edit" - app:showAsAction="ifRoom|withText" - android:title="@string/cache_menu_visit"> + android:title="@string/cache_menu_visit" + android:visible="false" + app:showAsAction="ifRoom|withText"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/main_activity_options.xml b/main/res/menu/main_activity_options.xml index b17080b..d556cdb 100644 --- a/main/res/menu/main_activity_options.xml +++ b/main/res/menu/main_activity_options.xml @@ -1,50 +1,51 @@ -<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto" >
-
- <!-- TODO: use ic_action_search -->
- <item
- android:id="@+id/menu_gosearch"
- style="@style/action_bar_action"
- android:icon="@drawable/abc_ic_search"
- android:title="@string/search_bar_hint"
- app:actionViewClass="android.support.v7.widget.SearchView"
- app:showAsAction="collapseActionView|always"/>
- <item
- android:id="@+id/menu_history"
- android:icon="@drawable/ic_menu_recent_history"
- android:title="@string/menu_history"
- app:showAsAction="ifRoom">
- </item>
- <item
- android:id="@+id/menu_pocket_queries"
- android:icon="@drawable/ic_menu_account_list"
- android:title="@string/menu_pocket_queries"
- app:showAsAction="ifRoom">
- </item>
- <item
- android:id="@+id/menu_settings"
- android:icon="@drawable/ic_menu_preferences"
- android:title="@string/menu_settings"
- app:showAsAction="ifRoom">
- </item>
- <item
- android:id="@+id/menu_helpers"
- android:icon="@drawable/ic_menu_shopping"
- android:title="@string/menu_helpers"
- app:showAsAction="ifRoom">
- </item>
- <item
- android:id="@+id/menu_scan"
- android:icon="@drawable/ic_menu_barcode"
- android:title="@string/menu_scan_geo"
- app:showAsAction="ifRoom">
- </item>
- <item
- android:id="@+id/menu_about"
- android:icon="@drawable/ic_menu_info_details"
- android:title="@string/menu_about"
- app:showAsAction="ifRoom">
- </item>
-
+<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" > + + <!-- TODO: use ic_action_search --> + <item + android:id="@+id/menu_gosearch" + style="@style/action_bar_action" + android:icon="@drawable/abc_ic_search" + android:title="@string/search_bar_hint" + app:actionViewClass="android.support.v7.widget.SearchView" + app:showAsAction="collapseActionView|always"/> + <item + android:id="@+id/menu_history" + android:icon="@drawable/ic_menu_recent_history" + android:title="@string/menu_history" + app:showAsAction="ifRoom"> + </item> + <item + android:id="@+id/menu_pocket_queries" + android:icon="@drawable/ic_menu_account_list" + android:title="@string/menu_pocket_queries" + android:visible="false" + app:showAsAction="ifRoom"> + </item> + <item + android:id="@+id/menu_settings" + android:icon="@drawable/ic_menu_preferences" + android:title="@string/menu_settings" + app:showAsAction="ifRoom"> + </item> + <item + android:id="@+id/menu_helpers" + android:icon="@drawable/ic_menu_shopping" + android:title="@string/menu_helpers" + app:showAsAction="ifRoom"> + </item> + <item + android:id="@+id/menu_scan" + android:icon="@drawable/ic_menu_barcode" + android:title="@string/menu_scan_geo" + app:showAsAction="ifRoom"> + </item> + <item + android:id="@+id/menu_about" + android:icon="@drawable/ic_menu_info_details" + android:title="@string/menu_about" + app:showAsAction="ifRoom"> + </item> + </menu>
\ No newline at end of file diff --git a/main/res/menu/map_activity.xml b/main/res/menu/map_activity.xml index 9559560..27e3840 100644 --- a/main/res/menu/map_activity.xml +++ b/main/res/menu/map_activity.xml @@ -26,6 +26,21 @@ android:icon="@drawable/ic_menu_refresh" android:showAsAction="ifRoom|withText" android:title="@string/map_live_disable" + android:visible="false" + app:showAsAction="ifRoom|withText"> + </item> + <item + android:id="@+id/menu_hint" + android:icon="@drawable/ic_menu_hint" + android:title="@string/cache_hint" + android:visible="false" + app:showAsAction="ifRoom|withText"> + </item> + <item + android:id="@+id/menu_compass" + android:icon="@drawable/ic_menu_compass" + android:title="@string/compass_title" + android:visible="false" app:showAsAction="ifRoom|withText"> </item> <item @@ -70,12 +85,14 @@ android:icon="@drawable/ic_menu_preferences" android:showAsAction="ifRoom|withText" android:title="@string/map_theme_select" + android:visible="false" app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/submenu_strategy" android:icon="@drawable/ic_menu_preferences" - android:title="@string/map_strategy"> + android:title="@string/map_strategy" + android:visible="false"> <menu> <group android:id="@+id/menu_group_strategy" diff --git a/main/res/menu/navigate_any_point_activity_options.xml b/main/res/menu/navigate_any_point_activity_options.xml index d4e4b9e..be9f589 100644 --- a/main/res/menu/navigate_any_point_activity_options.xml +++ b/main/res/menu/navigate_any_point_activity_options.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_default_navigation" diff --git a/main/res/menu/search_activity_options.xml b/main/res/menu/search_activity_options.xml index 300be94..ed84ebe 100644 --- a/main/res/menu/search_activity_options.xml +++ b/main/res/menu/search_activity_options.xml @@ -1,13 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_search_own_caches" android:icon="@drawable/ic_menu_myplaces" android:title="@string/search_own_caches" - app:showAsAction="ifRoom|withText" - > + app:showAsAction="ifRoom|withText"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/static_maps_activity_options.xml b/main/res/menu/static_maps_activity_options.xml index fb98f54..fdd7800 100644 --- a/main/res/menu/static_maps_activity_options.xml +++ b/main/res/menu/static_maps_activity_options.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_refresh" android:icon="@drawable/ic_menu_refresh" - app:showAsAction="ifRoom" - android:title="@string/cache_offline_refresh"> + android:title="@string/cache_offline_refresh" + app:showAsAction="ifRoom"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/trackable_activity.xml b/main/res/menu/trackable_activity.xml index 5bcd706..4b952d5 100644 --- a/main/res/menu/trackable_activity.xml +++ b/main/res/menu/trackable_activity.xml @@ -1,18 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_log_touch" android:icon="@drawable/ic_menu_edit" - app:showAsAction="ifRoom|withText" - android:title="@string/trackable_log_touch"> + android:title="@string/trackable_log_touch" + android:visible="false" + app:showAsAction="ifRoom|withText"> </item> <item android:id="@+id/menu_browser_trackable" android:icon="@drawable/ic_menu_info_details" - app:showAsAction="ifRoom|withText" - android:title="@string/trackable_browser_open"> + android:title="@string/trackable_browser_open" + android:visible="false" + app:showAsAction="ifRoom|withText"> </item> </menu>
\ No newline at end of file diff --git a/main/res/menu/waypoint_options.xml b/main/res/menu/waypoint_options.xml index 7df48f8..93333ed 100644 --- a/main/res/menu/waypoint_options.xml +++ b/main/res/menu/waypoint_options.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> - + xmlns:app="http://schemas.android.com/apk/res-auto" > + <item android:id="@+id/menu_waypoint_reset_cache_coords" android:title="@string/waypoint_reset_cache_coords"> @@ -30,4 +30,5 @@ android:id="@+id/menu_waypoint_caches_around" android:title="@string/cache_menu_around"> </item> -</menu> + +</menu>
\ No newline at end of file diff --git a/main/res/values-ca/strings.xml b/main/res/values-ca/strings.xml index e2d2c8f..934164c 100644 --- a/main/res/values-ca/strings.xml +++ b/main/res/values-ca/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">Visitat</string> <string name="log_tb_drop">Deixat</string> <string name="log_tb_changeall">Canvia-ho tot</string> - <string name="log_save">Desa</string> + <string name="log_save">Guarda-ho fora de lÃnia</string> <string name="log_saving">S\'està enviant el registre…</string> <string name="log_saving_and_uploading">S\'està enviant el registre i pujant la imatge…</string> <string name="log_clear">Esborra</string> <string name="log_post_not_possible">S\'està carregant la pà gina del registre…</string> + <string name="log_date_future_not_allowed">No estan permesos els registres amb data futura.</string> <string name="log_add">Afegeix</string> + <string name="log_repeat">Repeteix l\'últim registre</string> <string name="log_no_rating">Sense puntuació</string> <string name="log_stars_1_description">Pobre</string> <string name="log_stars_15_description">Bastant pobre</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Contrasenya d\'accés:</string> <string name="log_hint_log_password">Introduïu la contrasenya d\'accés</string> <string name="log_oc_team_comment">Comentari de l\'equip OC</string> + <string name="log_your_saved_log">El registre que heu desat</string> <string-array name="log_image_scales"> <item>Sense escala</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">No hi ha desada cap informació d\'accés</string> <string name="err_login_failed_toast">El c:geo no pot iniciar la sessió. El c:geo treballa fora lÃnia amb els catxés desats. Comproveu la configuració de la connexió o activeu la connexió a Internet.</string> <string name="err_unknown">Error desconegut</string> + <string name="err_unknown_address">c:geo no ha pogut assignar aquesta adreça a una ubicació existent</string> <string name="err_comm">S\'ha produït un error de comunicació desconegut</string> <string name="err_missing_auth">No s\'ha definit nom d\'usuari i/o contrasenya.</string> <string name="err_wrong">La informació d\'accés és incorrecta</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">S\'ha produït un error a l\'adquirir una imatge.</string> <string name="err_tb_display">El c:geo no pot mostrar el traçable que volÃeu. És realment un traçable?</string> <string name="err_tb_details_open">El c:geo no pot obrir els detalls del traçable.</string> - <string name="err_tb_forgot_saw">El c:geo no recorda quin traçable heu vist.</string> <string name="err_tb_find">El c:geo no pot trobar el traçable</string> <string name="err_tb_find_that">El c:geo no pot trobar aquest traçable.</string> <string name="err_waypoint_cache_unknown">El c:geo no sap a quin catxé voleu afegir la fita.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">El c:geo no pot reconèixer on ets.</string> <string name="err_point_no_position_given_title">Cal informació</string> <string name="err_point_no_position_given">Ompliu la latitud i la longitud o la distà ncia i la direcció. També podeu omplir els quatre camps.</string> - <string name="err_point_curr_position_unavailable">El c:geo encara no té les coordenades actuals. Espereu una estona…</string> <string name="err_point_bear_and_dist_title">Necessiteu ajuda?</string> <string name="err_point_bear_and_dist">Ompliu el rumb i la distà ncia. El rumb son angles del 0º al 360º respecte al Nord. La distà ncia no necessita unitats.</string> <string name="err_log_load_data">El c:geo no pot carregar les dades necessà ries per registrar la visita.</string> <string name="err_log_load_data_again">El c:geo no pot carregar les dades necessà ries per registrar la visita. Torneu a intentar-ho.</string> <string name="err_log_load_data_still">El c:geo encara està carregant les dades necessà ries per enviar el registre. Si us plau, espereu una estona més.</string> - <string name="err_log_post_failed">Sembla que el vostre registre no s\'ha publicat. Comproveu-ho a geocaching.com.</string> - <string name="err_log_post_failed_ec">Sembla que el registre no s\'ha publicat. Comproveu-ho a Extremcaching.com.</string> - <string name="err_logimage_post_failed">Sembla que la imatge de registre no ha estat guardada. Comproveu-ho a Geocaching.com.</string> + <string name="err_log_post_failed">El registre no s\'ha publicat. Comproveu la memòria del lloc web d\'origen.</string> + <string name="err_logimage_post_failed">La imatge de registre no s\'ha pujat. Comproveu la memòria del lloc web d\'origen.</string> <string name="err_search_address_forgot">El c:geo ha oblidat l\'adreça que intentaves trobar.</string> <string name="err_parse_lat">El c:geo no pot calcular la latitud.</string> <string name="err_parse_lon">El c:geo no pot calcular la longitud.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Xarxa</string> <string name="loc_fused">Combinat</string> <string name="loc_low_power">Bateria baixa</string> + <string name="loc_home">Coordenades de casa</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Intentant ubicar</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Propers</string> <string name="advanced_search_button">Cerca</string> <string name="stored_caches_button">Desats</string> - <string name="any_button">Vés a…</string> + <string name="any_button">Vés a</string> <string name="unknown_scan">No s\'ha trobat cap geocodi en el resultat de l\'exploració.</string> <string name="caches_no_cache">Aquà no hi ha catxés</string> <string name="caches_more_caches">Carrega més catxés</string> @@ -263,15 +265,22 @@ <string name="caches_sort_finds">Trobats</string> <string name="caches_sort_state">Estat</string> <string name="caches_sort_storage">Data d\'emmagatzemat al dispositiu</string> + <string name="caches_sort_eventdate">Data de la trobada</string> <string name="caches_select_mode">Mode seleccionar</string> <string name="caches_select_mode_exit">Surt del mode seleccionar</string> <string name="caches_select_invert">Inverteix la selecció</string> <string name="caches_nearby">Propers</string> <string name="caches_manage">Administra</string> <string name="caches_remove_all">Suprimeix-los tots</string> - <string name="caches_remove_all_confirm">Voleu suprimir tots els %s catxés de la llista actual?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Voleu suprimir aquest catxé de la llista actual?</item> + <item quantity="other">Voleu suprimir tots els %d catxés de la llista actual?</item> + </plurals> <string name="caches_remove_selected">Suprimeix els seleccionats</string> - <string name="caches_remove_selected_confirm">Voleu suprimir del dispositiu els %s catxés seleccionats?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Voleu suprimir aquest catxé del dispositiu?</item> + <item quantity="other">Voleu suprimir els %d catxés seleccionats del dispositiu?</item> + </plurals> <string name="caches_remove_progress">S\'estan eliminant els catxés</string> <string name="caches_delete_events">Elimina trobades passades</string> <string name="caches_refresh_selected">Actualitza els seleccionats</string> @@ -291,13 +300,18 @@ <string name="caches_filter_track">Amb traçables</string> <string name="caches_filter_clear">Neteja els filtres</string> <string name="caches_filter_modified">Amb les coordenades modificades</string> + <string name="caches_filter_offline_log">Amb registre fora de lÃnia</string> <string name="caches_filter_origin">Origen</string> <string name="caches_filter_distance">Distà ncia</string> <string name="caches_filter_personal_note">Amb una nota personal</string> <string name="caches_filter_popularity">Preferits</string> <string name="caches_filter_popularity_ratio">Preferits [%]</string> + <string name="caches_filter_personal_data">Amb dades personals</string> + <string name="caches_filter_rating">Amb puntuació</string> + <string name="caches_filter_own_rating">Amb puntuació pròpia</string> <string name="caches_removing_from_history">S\'està eliminant de l\'historial…</string> <string name="caches_clear_offlinelogs">Neteja els registres fora de lÃnea</string> + <string name="caches_clear_offlinelogs_message">Voleu esborrar els registres fora de lÃnia?</string> <string name="caches_clear_offlinelogs_progress">S\'estan netejant els registres fora lÃnia</string> <string name="list_menu_create">Crea una llista nova</string> <string name="list_menu_drop">Elimina la llista actual</string> @@ -320,13 +334,17 @@ <string name="list_not_available">La llista ja no està disponible, s\'està canviant a la llista està ndard</string> <string name="about_version">Versió</string> <string name="about_changelog">Historial de canvis</string> + <string name="about_system">Sistema</string> <string name="about_donate">Donatiu</string> <string name="about_donation_more">Donatiu\nal desenvolupament</string> <string name="about_contributors">Col·laboradors</string> <string name="about_license">Llicència</string> <string name="about_apache_license"><a href="">Llicència Apache, versió 2.0</a></string> <string name="about_help">Ajuda</string> + <string name="about_system_include">Si us plau incloure la següent informació de sistema quan envieu un informe d\'error o demanar més informació sobre c:geo:</string> + <string name="changelog_github">Llista de tots els canvis</string> <string name="settings_title_services">Serveis</string> + <string name="settings_summary_services">Configureu la informació del compte d\'usuari i l\'accés a serveis opcionals.</string> <string name="settings_title_appearance">Aparença</string> <string name="settings_title_cachedetails">Detalls del catxé</string> <string name="settings_title_offlinedata">Dades fora de lÃnia</string> @@ -373,6 +391,9 @@ <string name="settings_activate_oc_uk">Activa</string> <string name="init_oc_uk_description">Autoritza al c:geo a opencaching.org.uk per buscar catxés i accedir/filtrar els teus catxés trobats.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Per poder puntuar un catxé, cal seguir les instruccions a GCVote.com i introduir aquà la contrasenya del GCVote.</string> + <string name="err_gcvote_send_rating">Hi ha un error al enviar la puntuació, comproveu la contrasenya de GCVote a les opcions o deixeu-ho buit.</string> + <string name="gcvote_sent">Votació enviada correctament</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activa</string> <string name="init_username">Nom d\'usuari</string> @@ -443,6 +464,8 @@ <string name="init_backup_success">La base de dades del c:geo s\'ha copiat amb èxit a:</string> <string name="init_backup_failed">Ha fallat la còpia de seguretat de la base de dades de c:geo.</string> <string name="init_backup_unnecessary">La base de dades està buida, no cal fer una còpia de seguretat.</string> + <string name="backup_confirm_overwrite">Voleu sobreescriure la còpia de seguretat existent de %s?</string> + <string name="restore_confirm_overwrite">Voleu sobreescriure %s al dispositiu amb la còpia de seguretat?</string> <string name="init_restore_success">La restauració s\'ha completat.</string> <string name="init_restore_failed">Ha fallat la restauració.</string> <string name="init_restore_running">S\'està restaurant la base de dades dels catxés…</string> @@ -604,6 +627,7 @@ </plurals> <string name="cache_waypoints_add">Afegeix una fita</string> <string name="cache_hint">Pista</string> + <string name="cache_hint_not_available">No hi ha cap pista disponible</string> <string name="cache_logs">Llibre de registre</string> <string name="cache_logs_friends_and_own">Registres dels amics o propis</string> <string name="cache_dialog_loading_details">S\'està carregant els detalls del catxé…</string> @@ -643,9 +667,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Obre al navegador</string> <string name="cache_menu_visit">Registra visita</string> - <string name="cache_menu_visit_offline">Registra visita fora de lÃnia</string> + <string name="cache_menu_visit_offline">Registra fora de lÃnia amb un sol clic</string> <string name="cache_menu_spoilers">Imatges d\'ajuda</string> <string name="cache_menu_around">Catxés propers</string> + <string name="around">Al voltant de %s</string> <string name="cache_menu_event">Afegeix al calendari</string> <string name="cache_menu_details">Detalls</string> <string name="cache_menu_refresh">Actualitza</string> @@ -655,6 +680,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Vota</string> + <string name="cache_menu_checker">Obre el Geochecker</string> + <string name="cache_menu_ignore">Ignora el catxé</string> <string name="cache_status">Estat</string> <string name="cache_status_offline_log">Registre desat</string> <string name="cache_status_found">Trobat</string> @@ -740,6 +768,7 @@ <string name="waypoint_note">Nota</string> <string name="waypoint_visited">Visitat</string> <string name="waypoint_save">Desa</string> + <string name="waypoint_cancel_edit">Cancel•la</string> <string name="waypoint_loading">S\'està carregant la fita…</string> <string name="waypoint_do_not_touch_cache_coordinates">No s\'ha fet cap canvi a les coordenades del catxé</string> <string name="waypoint_set_as_cache_coords">Estableix com a coordenades del catxé al c:geo</string> @@ -764,6 +793,8 @@ <string name="search_clear_history">Esborra l\'historial</string> <string name="search_history_cleared">S\'ha esborrat l\'historial</string> <string name="waypoint_coordinate_formats_plain">Senzill</string> + <string name="from_clipboard">Des del porta-retalls</string> + <string name="copy_to_clipboard">Copia al porta-retalls</string> <string name="visit_tweet">Envia aquest \"trobat\" al Twitter</string> <string name="map_map">Mapa</string> <string name="map_live">Mapa en viu</string> @@ -868,7 +899,7 @@ <string name="helper_contacts_description">Us permet obrir un contacte (de la llibreta de contactes) directament des d\'una entrada del registre, aixà podeu demanar ajuda als amics més fà cilment.</string> <string name="helper_sendtocgeo_description">Send to c:geo és una extensió del navegador <strong>per al vostre ordinador</strong>. Quan navegueu per geocaching.com podreu enviar catxés des del navegador directament al vostre telèfon amb un clic de botó.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Aplicació simple que mostra mapes en lÃnia i us permet descarregar-los directament pel mode fora de lÃnia (només mapes raster). També suporta la gravació de rutes, manipulació de punts d\'interès i moltes altres funcions útils.</string> + <string name="helper_locus_description">Aplicació de navegació a l\'aire lliure per al vostre telèfon o tauleta. Podeu veure mapes topogrà fics fora de lÃnia, seguir una ruta, trobar geocatxés, utilitzar una guia de veu i molt més.</string> <string name="helper_gpsstatus_title">Estat del GPS</string> <string name="helper_gpsstatus_description">Podeu utilitzar el radar en aquesta aplicació conjuntament amb el c:geo. També ofereix moltes altres informacions relacionades amb el GPS.</string> <string name="helper_bluetoothgps_title">GPS Bluetooth</string> @@ -1120,13 +1151,15 @@ <string name="attribute_offset_cache_no">No és un catxé offset</string> <string name="quote">Per fer el geocatxing més fà cil, per fer els usuaris més dropos.</string> <string name="powered_by">Carnero</string> - <string name="support">Suport: <a href="">support@cgeo.org</a></string> - <string name="website">Lloc web: <a href=""> cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">Pà gina del c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">El c:geo a Google Play</a></string> + <string name="support_title">Ajut</string> + <string name="website_title">Lloc web</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">Pà gina del c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href=""> c:geo a Google Play</a></string> <string name="about_twitter">Voleu que <b>el c:geo</b> publiqui un nou estatus al Twitter cada vegada que registreu un catxé?</string> - <string name="faq">PMF: <a href=""> faq.cgeo.org</a></string> + <string name="faq_title">Preguntes freqüents</string> <string name="status_new_release" tools:ignore="UnusedResources">Nova versió disponible.\nCliqueu per instal·lar-la.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nova versió nightly build disponible.\nCliqueu per instal·lar-la.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nova versió candidate disponible.\nCliqueu per instal·lar-la.</string> @@ -1171,7 +1204,7 @@ <item quantity="one">%s preferit</item> <item quantity="other">%s preferits</item> </plurals> - <string name="percent_favorite_points">% \ preferits</string> + <string name="more_than_percent_favorite_points">> %d%% preferits</string> <string name="cgeo_shortcut">Drecera del c:geo</string> <string name="create_shortcut">Crea una drecera</string> <string name="send">Envia</string> @@ -1181,6 +1214,8 @@ <string name="showcase_main_text">Ara el c:geo posa elements del menú a la barra de tÃtol al igual que altres aplicacions modernes. Alguns elements s\'amaguen darrere el sÃmbol de punts. Premeu el botó de forma llarga per veure la seva descripció.</string> <string name="showcase_cachelist_title">Llista de canvis</string> <string name="showcase_cachelist_text">Es pot canviar entre les diferents llistes fent un clic al nom de la llista actual.</string> + <string name="showcase_compass_hint_title">Mostrar la pista</string> + <string name="showcase_compass_hint_text">Aquest element de menú nou podria donar una idea on trobar l\'amagatall - li mostra la pista, si està disponible.</string> <string name="confirm_log_title">Tipus de registre poc habitual</string> <string name="confirm_log_message">Voleu registrar \'%s\'. N\'esteu segurs?</string> </resources> diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index 9ab2d11..e677227 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -8,14 +8,14 @@ <string name="about">O aplikaci</string> <string name="latitude">ZemÄ›pisná Å¡ÃÅ™ka</string> <string name="longitude">ZemÄ›pisná délka</string> - <string name="settings_titlebar">c:geo NastavenÃ</string> + <string name="settings_titlebar">Nastavenà c:geo</string> <string name="all_types">VÅ¡echny typy keÅ¡Ã</string> <string name="traditional">TradiÄnà keÅ¡</string> <string name="multi">Multi keÅ¡</string> <string name="mystery">Mystery keÅ¡</string> - <string name="letterbox">Dopisnà schránka</string> - <string name="event">KeÅ¡ události</string> - <string name="mega">KeÅ¡ Mega-události</string> + <string name="letterbox">Letterbox keÅ¡</string> + <string name="event">Událost</string> + <string name="mega">Mega-událost</string> <string name="giga">Giga event</string> <string name="earth">Earthcache</string> <string name="cito">Událost Cache In Trash Out</string> @@ -73,12 +73,14 @@ <string name="log_tb_visit">NavÅ¡tÃveno</string> <string name="log_tb_drop">Nechat zde</string> <string name="log_tb_changeall">ZmÄ›nit vÅ¡e</string> - <string name="log_save">Uložit</string> + <string name="log_save">Uložit offline</string> <string name="log_saving">OdesÃlánà Logu…</string> <string name="log_saving_and_uploading">OdesÃlánà Logu a nahrávánà obrázku…</string> <string name="log_clear">VyÄistit</string> <string name="log_post_not_possible">NaÄÃtánà stránky s LogovacÃm formulářem…</string> + <string name="log_date_future_not_allowed">Log s nadcházejÃcÃm datem nenà povolen.</string> <string name="log_add">PÅ™idat</string> + <string name="log_repeat">Opakovat poslednà log</string> <string name="log_no_rating">Bez hodnocenÃ</string> <string name="log_stars_1_description">Slabá</string> <string name="log_stars_15_description">Docela slabá</string> @@ -106,6 +108,7 @@ <string name="log_password_title">Logovacà heslo:</string> <string name="log_hint_log_password">Zadej své logovacà heslo</string> <string name="log_oc_team_comment">Komentář týmu OC</string> + <string name="log_your_saved_log">Tvé uložené logy</string> <string-array name="log_image_scales"> <item>Bez měřÃtka</item> <item>512 px</item> @@ -123,6 +126,7 @@ <string name="err_login">Nejsou uloženy žádné pÅ™ihlaÅ¡ovacà údaje</string> <string name="err_login_failed_toast">Nelze se pÅ™ihlásit. c:geo bude pracovat Offline s uloženými informacemi. Zkontroluj nastavenà pÅ™ihlaÅ¡ovánà a pÅ™ipojenà k Internetu.</string> <string name="err_unknown">Neznámá chyba</string> + <string name="err_unknown_address">c:geo nedokázal tuto adresu najÃt na mapÄ›</string> <string name="err_comm">Neznámá komunikaÄnà chyba</string> <string name="err_missing_auth">Nenastaveno žádné pÅ™ihlaÅ¡ovacà jméno/heslo.</string> <string name="err_wrong">Chybné pÅ™ihlaÅ¡ovacà údaje</string> @@ -157,7 +161,6 @@ <string name="err_acquire_image_failed">ZÃskánà obrázku selhalo.</string> <string name="err_tb_display">c:geo nemůže zobrazit sledovatelný pÅ™edmÄ›t. Je to opravdu sledovatelný pÅ™edmÄ›t?</string> <string name="err_tb_details_open">c:geo nemůže otevÅ™Ãt podrobnosti ke sledovatelnému pÅ™edmÄ›tu.</string> - <string name="err_tb_forgot_saw">c:geo zapomÄ›lo, který sledovatelný pÅ™edmÄ›t jsi prohlÞel/a.</string> <string name="err_tb_find">c:geo nemůže najÃt sledovatelný pÅ™edmÄ›t.</string> <string name="err_tb_find_that">c:geo nemůže najÃt tento sledovatelný pÅ™edmÄ›t.</string> <string name="err_waypoint_cache_unknown">c:geo nevà k jaké keÅ¡i chceÅ¡ pÅ™idat bod trasy.</string> @@ -165,15 +168,13 @@ <string name="err_point_unknown_position">c:geo nedokáže zjistit tvou polohu.</string> <string name="err_point_no_position_given_title">Popis je vyžadován</string> <string name="err_point_no_position_given">Vyplň alespoň zemÄ›pisnou Å¡ÃÅ™ku a délku nebo vzdálenost a smÄ›r. MůžeÅ¡ také vyplnit vÅ¡echna ÄtyÅ™i pole.</string> - <string name="err_point_curr_position_unavailable">c:geo stále nemá aktuálnà souÅ™adnice. ProsÃm, chvilku poÄkej…</string> <string name="err_point_bear_and_dist_title">PotÅ™ebujeÅ¡ poradit?</string> <string name="err_point_bear_and_dist">Vyplň smÄ›r i vzdálenost. SmÄ›r je úhel 0 až 360 stupňů vzhledem k severu. Vzdálenost s nebo bez jednotek.</string> <string name="err_log_load_data">c:geo nemůže naÄÃst data požadovaná k zalogovánà návÅ¡tÄ›vy.</string> <string name="err_log_load_data_again">c:geo nemůže naÄÃst data požadovaná k zalogovánà návÅ¡tÄ›vy. ZkouÅ¡Ã to znovu.</string> <string name="err_log_load_data_still">c:geo stále naÄÃtá data požadovaná k odeslánà Logu. ProsÃm, poÄkej jeÅ¡tÄ› chvÃli.</string> - <string name="err_log_post_failed">Zdá se, že tvůj Log nebyl odeslán. ProsÃm, zkontroluj to na Geocaching.com.</string> - <string name="err_log_post_failed_ec">Zdá se, že tvůj Log nebyl odeslán. ProsÃm, zkontroluj to na Extremcaching.com.</string> - <string name="err_logimage_post_failed">Zdá se, že tvůj obrázek nebyl nahrán. Zkontroluj to, prosÃm, na Geocaching.com.</string> + <string name="err_log_post_failed">Zdá se, že tvůj log nebyl správnÄ› zveÅ™ejnÄ›n. ProsÃm, zkontroluj ho pÅ™Ãmo na webové stránce keÅ¡e.</string> + <string name="err_logimage_post_failed">Zdá se, že obrázek u logu nebyl správnÄ› odeslán. ProsÃm, zkontroluj to pÅ™Ãmo na webové stránce keÅ¡e.</string> <string name="err_search_address_forgot">c:geo zapomnÄ›lo hledanou adresu.</string> <string name="err_parse_lat">c:geo nemůže dopoÄÃtat zemÄ›pisnou Å¡ÃÅ™ku.</string> <string name="err_parse_lon">c:geo nemůže dopoÄÃtat zemÄ›pisnou délku.</string> @@ -210,13 +211,14 @@ <string name="loc_net">SÃÅ¥</string> <string name="loc_fused">Kombinovaný</string> <string name="loc_low_power">NÃzká spotÅ™eba</string> + <string name="loc_home">SouÅ™adnice domova</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">ZjiÅ¡Å¥ovánà pozice</string> <string name="loc_no_addr">Neznámá adresa</string> <string name="loc_gps_disabled">GPS zakázáno</string> <string name="menu_centerposition">Vycentrovat na mou polohu</string> - <string name="menu_about">O programu</string> + <string name="menu_about">O aplikaci</string> <string name="menu_helpers">Pomocné programy</string> <string name="menu_settings">NastavenÃ</string> <string name="menu_history">Historie</string> @@ -228,7 +230,7 @@ <string name="caches_nearby_button">NejbližšÃ</string> <string name="advanced_search_button">HledánÃ</string> <string name="stored_caches_button">Uložené</string> - <string name="any_button">CÃl</string> + <string name="any_button">PÅ™ejÃt</string> <string name="unknown_scan">Ve výsledku skenu nenalezen žádný geokód.</string> <string name="caches_no_cache">Žádná keÅ¡</string> <string name="caches_more_caches">NaÄÃst dalÅ¡Ã keÅ¡e</string> @@ -240,7 +242,7 @@ <plurals name="caches_eta_mins"> <item quantity="one">%d minuta</item> <item quantity="few">%d minuty</item> - <item quantity="other">%d minuty</item> + <item quantity="other">%d minut</item> </plurals> <string name="caches_store_offline">Uložit pro offline</string> <string name="caches_store_selected">Uložit vybrané</string> @@ -263,15 +265,24 @@ <string name="caches_sort_finds">PoÄtu nálezů</string> <string name="caches_sort_state">Stavu</string> <string name="caches_sort_storage">Data uloženà do zaÅ™ÃzenÃ</string> + <string name="caches_sort_eventdate">Datum události</string> <string name="caches_select_mode">Mód výbÄ›ru</string> <string name="caches_select_mode_exit">Opustit mód výbÄ›ru</string> <string name="caches_select_invert">Invertovat výbÄ›r</string> <string name="caches_nearby">BlÃzké</string> <string name="caches_manage">Správa</string> <string name="caches_remove_all">Odstranit vÅ¡e</string> - <string name="caches_remove_all_confirm">Opravdu chceÅ¡ smazat vÅ¡echny keÅ¡e (%s) z tohoto seznamu?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Opravdu chceÅ¡ smazat tuto keÅ¡ z aktuálnÃho seznamu?</item> + <item quantity="few">Opravdu chceÅ¡ smazat vÅ¡echny keÅ¡e (%d) ze seznamu?</item> + <item quantity="other">Opravdu chceÅ¡ smazat vÅ¡echny keÅ¡e (%d) ze seznamu?</item> + </plurals> <string name="caches_remove_selected">Odstranit vybrané</string> - <string name="caches_remove_selected_confirm">Opravdu chceÅ¡ smazat vybrané keÅ¡e (%s) z pÅ™Ãstroje?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Opravdu chceÅ¡ tuto keÅ¡ odstranit z tvého zaÅ™ÃzenÃ?</item> + <item quantity="few">Opravdu chceÅ¡ odstranit vybrané keÅ¡e (%d) z tvého zaÅ™ÃzenÃ?</item> + <item quantity="other">Opravdu chceÅ¡ odstranit vybrané keÅ¡e (%d) z tvého zaÅ™ÃzenÃ?</item> + </plurals> <string name="caches_remove_progress">Odstraňovánà keÅ¡Ã</string> <string name="caches_delete_events">Vymazat staré události</string> <string name="caches_refresh_selected">Aktualizovat vybrané</string> @@ -291,13 +302,18 @@ <string name="caches_filter_track">Se sledovatelnými pÅ™edmÄ›ty</string> <string name="caches_filter_clear">Vymazat filtry</string> <string name="caches_filter_modified">S upravenými souÅ™adnicemi</string> + <string name="caches_filter_offline_log">S offline logy</string> <string name="caches_filter_origin">Původ keÅ¡e</string> <string name="caches_filter_distance">Vzdálenost</string> <string name="caches_filter_personal_note">S osobnà poznámkou</string> <string name="caches_filter_popularity">OblÃbené</string> <string name="caches_filter_popularity_ratio">OblÃbené [%]</string> + <string name="caches_filter_personal_data">S osobnÃmi údaji</string> + <string name="caches_filter_rating">S hodnocenÃm</string> + <string name="caches_filter_own_rating">S vlastnÃm hodnocenÃm</string> <string name="caches_removing_from_history">ÄŒiÅ¡tÄ›nà Historie…</string> <string name="caches_clear_offlinelogs">Smazat offline Logy</string> + <string name="caches_clear_offlinelogs_message">Opravdu chceÅ¡ vymazat offline logy?</string> <string name="caches_clear_offlinelogs_progress">Mazánà offline logů</string> <string name="list_menu_create">VytvoÅ™it nový seznam</string> <string name="list_menu_drop">Smazat aktuálnà seznam</string> @@ -311,7 +327,7 @@ <string name="list_dialog_create_ok">Nový seznam byl vytvoÅ™en</string> <string name="list_dialog_create_err">c:geo nedokázalo vytvoÅ™it nový seznam</string> <string name="list_dialog_remove_title">Odstranit seznam</string> - <string name="list_dialog_remove_description">ChceÅ¡ odstranit aktuálnà seznam keÅ¡Ã? VÅ¡echny zbývajÃcà keÅ¡e budou pÅ™esunuty do seznamu \"Uložené\".</string> + <string name="list_dialog_remove_description">ChceÅ¡ odstranit aktuálnà seznam keÅ¡Ã? VÅ¡echny zbývajÃcà keÅ¡e budou pÅ™esunuty do seznamu „Uložené“.</string> <string name="list_dialog_remove">Odstranit</string> <string name="list_dialog_remove_ok">Seznam byl odstranÄ›n</string> <string name="list_dialog_remove_err">c:geo nedokázalo odstranit aktuálnà seznam</string> @@ -320,13 +336,17 @@ <string name="list_not_available">Seznam již nenà dostupný, pÅ™epÃnánà na výchozà seznam</string> <string name="about_version">Verze</string> <string name="about_changelog">ZmÄ›ny</string> + <string name="about_system">Systém</string> <string name="about_donate">Podpora vývoje</string> <string name="about_donation_more">PodpoÅ™it\nvývoj</string> <string name="about_contributors">PÅ™ispÃvajÃcÃ</string> <string name="about_license">Licence</string> <string name="about_apache_license"><a href=""> licence Apache, verze 2.0</a></string> <string name="about_help">NápovÄ›da</string> + <string name="about_system_include">PÅ™i odesÃlánà hlášenà o chybÄ› nebo žádosti o dalÅ¡Ã informace uveÄte prosÃm následujÃcà systémové informace:</string> + <string name="changelog_github">Seznam vÅ¡ech zmÄ›n</string> <string name="settings_title_services">Služby</string> + <string name="settings_summary_services">Nastavenà uživatelského úÄtu a pÅ™Ãstupu k volitelným službám.</string> <string name="settings_title_appearance">Vzhled</string> <string name="settings_title_cachedetails">Detaily keÅ¡e</string> <string name="settings_title_offlinedata">Offline zdroje</string> @@ -374,6 +394,9 @@ <string name="settings_activate_oc_uk">Aktivovat</string> <string name="init_oc_uk_description">Autorizovat c:geo pro hledánà keÅ¡Ã a pÅ™Ãstup/filtrovánà tvých nalezených keÅ¡Ã služby opencaching.org.uk.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Pokud chceÅ¡ hodnotit keÅ¡e, je tÅ™eba postupovat dle pokynů na GCVote.com a zadat sem své heslo.</string> + <string name="err_gcvote_send_rating">Chyba pÅ™i odesÃlánà hodnocenÃ, zkontroluj GCVote heslo v nastavenà nebo ho nech prázdné.</string> + <string name="gcvote_sent">Hlas úspěšnÄ› odeslán</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Povolit</string> <string name="init_username">Uživatelské jméno</string> @@ -444,6 +467,8 @@ <string name="init_backup_success">Databáze c:geo byla úspěšnÄ› zkopÃrována do souboru</string> <string name="init_backup_failed">Zálohovánà databáze c:geo selhalo.</string> <string name="init_backup_unnecessary">Databáze je prázdná, takže nenà tÅ™eba zálohovat.</string> + <string name="backup_confirm_overwrite">Opravdu chceÅ¡ pÅ™esat existujÃcà zálohu z %s?</string> + <string name="restore_confirm_overwrite">ChceÅ¡ pÅ™epsat %s na svém zaÅ™Ãzenà zálohou?</string> <string name="init_restore_success">Obnova dokonÄena.</string> <string name="init_restore_failed">Obnova selhala.</string> <string name="init_restore_running">Obnovovánà databáze keÅ¡Ã…</string> @@ -451,7 +476,7 @@ <string name="init_backup_last">Dostupná záloha z</string> <string name="init_backup_last_no">Nenalezen žádný soubor se zálohou.</string> <string name="settings_info_offline_maps_title">Info o Offline mapách</string> - <string name="settings_info_offline_maps">c:geo podporuje použÃvánà offline map. Mapy si můžeÅ¡ stáhnout z Mapsforge a nebo si vytvoÅ™it vlastnà z dat Open Street Map (OSM). Aby bylo možné offline mapy použÃvat, musÃÅ¡ nejprve zvolit mÃsto jejich uloženÃ.</string> + <string name="settings_info_offline_maps">c:geo podporuje použÃvánà offline mapových podkladů, které si můžeÅ¡ stáhnout z Mapsforge a nebo si vytvoÅ™it vlastnà z dat Open Street Map (OSM). Aby bylo možné offline mapy použÃvat, musÃÅ¡ nejprve zvolit mÃsto jejich umÃstÄ›nà (volba „Složka s offline mapami“).</string> <string name="settings_info_themes_title">Info o stylech mapy</string> <string name="settings_info_themes">c:geo podporuje vlastnà styly pro offline mapy. Ty mohou být použity pro zmÄ›nu barevného stylu mapy (napÅ™. noÄnà mapa), pro zvýraznÄ›nà důležitých objektů (jako jsou napÅ™. cykloztezky) nebo pro urÄenà šÃÅ™ky Äar.</string> <string name="init_mapsource_select">Vyber mapový zdroj</string> @@ -533,7 +558,7 @@ <string name="init_sendToCgeo">Poslat do c:geo</string> <string name="settings_info_send2cgeo_title">Info o funkci send2c:geo</string> <string name="init_sendToCgeo_name">Název tvého zaÅ™ÃzenÃ</string> - <string name="init_sendToCgeo_description">Funkce <b>Send2c:geo</b> umožňuje stahovat keÅ¡e pÅ™Ãmo ze stránky Geocaching.com pomocà speciálnÃho doplňku pro webové prholÞeÄe. PÅ™ed registracà zkoukni <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Pokud chceÅ¡ použÃvat funkci send2c:geo, musÃÅ¡ se zaregistrovat. c:geo může samozÅ™ejmÄ› pracovat normálnÄ› i bez registrace této funkce.</string> + <string name="init_sendToCgeo_description">Funkce <b>Send2c:geo</b> umožňuje stahovat keÅ¡e pÅ™Ãmo ze stránky Geocaching.com pomocà speciálnÃho doplňku pro webové prohlÞeÄe. PÅ™ed registracà zkoukni <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Pokud chceÅ¡ použÃvat funkci send2c:geo, musÃÅ¡ se zaregistrovat. Aplikace c:geo může samozÅ™ejmÄ› pracovat normálnÄ› i bez registrace této funkce.</string> <string name="init_sendToCgeo_register">Požádat o registraci</string> <string name="init_sendToCgeo_registering">Registrace tvého zaÅ™Ãzenà pro funkci Poslat do c:geo…</string> <string name="init_sendToCgeo_register_ok">Registrace úspěšnÄ› dokonÄena. PIN kód je ####. Použij ho na stránce c:geo pro pÅ™idánà zaÅ™Ãzenà do tvého prohlÞeÄe.</string> @@ -546,7 +571,7 @@ <string name="auth_again">Znovu autorizovat</string> <string name="auth_dialog_waiting">ÄŒekánà na %s…</string> <string name="auth_explain_short">NásledujÃcà proces umožnà <b>c:geu</b> pÅ™Ãstup k %s.</string> - <string name="auth_explain_long">StisknutÃm tlaÄÃtka \"Autorizovat c:geo\" bude proces zahájen. Tento proces otevÅ™e webový prohlÞeÄ se stránkou %s. Na této stránce se pÅ™ihlaÅ¡ a povol <b>c:geu</b> pÅ™istupovat k tvému úÄtu. To je vÅ¡e.</string> + <string name="auth_explain_long">StisknutÃm tlaÄÃtka „Autorizovat c:geo“ bude proces zahájen. Tento proces otevÅ™e webový prohlÞeÄ se stránkou %s. Na této stránce se pÅ™ihlaÅ¡ a povol <b>c:geu</b> pÅ™istupovat k tvému úÄtu. To je vÅ¡e.</string> <string name="auth_dialog_completed_twitter">c:geo nynà může posÃlat zprávy na Tvůj Twitter.</string> <string name="auth_ocde">Opencaching.de</string> <string name="auth_ocpl">opencaching.pl</string> @@ -555,6 +580,11 @@ <string name="auth_ocro">opencaching.ro</string> <string name="auth_ocuk">opencaching.org.uk</string> <string name="auth_dialog_completed_oc">c:geo je nynà autorizováno pro interakce s %s.</string> + <plurals name="cache_counts"> + <item quantity="one">Jedna keÅ¡</item> + <item quantity="few">%1$d keÅ¡e</item> + <item quantity="other">%1$d keÅ¡Ã</item> + </plurals> <string name="cache_offline">Offline</string> <string name="cache_offline_refresh">Obnovit</string> <string name="cache_offline_drop">Smazat</string> @@ -603,6 +633,7 @@ </plurals> <string name="cache_waypoints_add">PÅ™idat Bod trasy</string> <string name="cache_hint">NápovÄ›da</string> + <string name="cache_hint_not_available">NápovÄ›da nenà dostupná</string> <string name="cache_logs">Logbook</string> <string name="cache_logs_friends_and_own">Moje logy a logy přátel</string> <string name="cache_dialog_loading_details">NaÄÃtánà detailů keÅ¡e…</string> @@ -642,9 +673,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">OtevÅ™Ãt v prohlÞeÄÃ</string> <string name="cache_menu_visit">Zalogovat návÅ¡tÄ›vu</string> - <string name="cache_menu_visit_offline">Zapsat návÅ¡tÄ›vu (offline)</string> + <string name="cache_menu_visit_offline">Rychlý offline log</string> <string name="cache_menu_spoilers">Obrázky</string> <string name="cache_menu_around">KeÅ¡ v okolÃ</string> + <string name="around">V okolà %s</string> <string name="cache_menu_event">PÅ™idat do kalendáře</string> <string name="cache_menu_details">Detaily</string> <string name="cache_menu_refresh">Obnovit</string> @@ -654,6 +686,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Hlasovat</string> + <string name="cache_menu_checker">OtevÅ™Ãt Geocheck</string> + <string name="cache_menu_ignore">Ignorovat keÅ¡</string> <string name="cache_status">Stav</string> <string name="cache_status_offline_log">PÅ™ipravený Log</string> <string name="cache_status_found">Nalezena</string> @@ -739,6 +774,7 @@ <string name="waypoint_note">Poznámka</string> <string name="waypoint_visited">NavÅ¡tÃven</string> <string name="waypoint_save">Uložit</string> + <string name="waypoint_cancel_edit">ZruÅ¡it</string> <string name="waypoint_loading">NaÄÃtánà bodu trasy…</string> <string name="waypoint_do_not_touch_cache_coordinates">NemÄ›nit souÅ™adnice keÅ¡e</string> <string name="waypoint_set_as_cache_coords">Nastavit jako souÅ™adnice keÅ¡e v c:geo</string> @@ -763,6 +799,8 @@ <string name="search_clear_history">Vymazat historii</string> <string name="search_history_cleared">Historie vymazána</string> <string name="waypoint_coordinate_formats_plain">Prostý</string> + <string name="from_clipboard">Ze schránky</string> + <string name="copy_to_clipboard">KopÃrovat do schránky</string> <string name="visit_tweet">Oznámit nález na Twitteru</string> <string name="map_map">Mapa</string> <string name="map_live">Aktivnà mapa</string> @@ -785,7 +823,7 @@ <string name="map_strategy_fast">Rychlá</string> <string name="map_strategy_auto">Závislá na rychlosti</string> <string name="map_strategy_detailed">DetailnÃ</string> - <string name="live_map_notification">Na nové Aktivnà mapÄ› nemusà být souÅ™adnice vždy pÅ™esné. PÅ™Ãpadné nepÅ™esné souÅ™adnice jsou na mapÄ› oznaÄeny oranžovým kruhem.\nPÅ™i otevÅ™enà detailů keÅ¡e nebo jejÃm uloženà pro Offline použità jsou již souÅ™adnice pÅ™esné.\n\nVÃce informacà o vÅ¡ech zmÄ›nách lze najÃt na stránce \"O programu\" v aplikaci.</string> + <string name="live_map_notification">Na nové Aktivnà mapÄ› nemusà být souÅ™adnice vždy pÅ™esné. PÅ™Ãpadné nepÅ™esné souÅ™adnice jsou na mapÄ› oznaÄeny oranžovým kruhem.\nPÅ™i otevÅ™enà detailů keÅ¡e nebo jejÃm uloženà pro Offline použità jsou již souÅ™adnice pÅ™esné.\n\nVÃce informacà o vÅ¡ech zmÄ›nách lze najÃt v aplikaci na stránce „O aplikaci“.</string> <string name="search_bar_hint">Hledanà keÅ¡ek</string> <string name="search_bar_desc">KeÅ¡e (GC-kód, klÃÄové slovo), Sledovatelné pÅ™edmÄ›ty (TB-kód)</string> <string name="search_coordinates">SouÅ™adnice</string> @@ -867,7 +905,7 @@ <string name="helper_contacts_description">Umožňuje otevÅ™Ãt vizitku (z tvého seznamu kontaktů) pÅ™Ãmo z logu keÅ¡e, můžeÅ¡ tak snadnÄ›ji kontaktovat kamarády o pomoc.</string> <string name="helper_sendtocgeo_description">Poslat do c:geo (Send2c:geo) je rozÅ¡ÃÅ™enà prohlÞeÄe <strong>pro tvůj poÄÃtaÄ</strong>. Umožňuje zaslánà keÅ¡e do tvého mobilnÃho zaÅ™Ãzenà jediným klepnutÃm, pÅ™Ãmo z prohlÞeÄe, pÅ™i procházenà webu Geocaching.com.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">JednoduÅ¡e použitelná aplikace zobrazujÃcà Online mapy a dovolujÃcà je pÅ™Ãmo stahovat pro Offline použità (pouze rastrové mapy). Také podporuje záznam trasy, zpracovánà bodů zájmu a dalÅ¡Ã užiteÄné funkce.</string> + <string name="helper_locus_description">Outdoorová navigace pro telefon Äi tablet. ProhlÞenà offline topo map, záznam trasy, lov geokeÅ¡Ã, hlasová navigace a mnohem vÃce.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">MůžeÅ¡ použÃt radar z této aplikace pro c:geo. Také podporuje dalÅ¡Ã funkce spojené s použÃvánÃm GPS.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1117,15 +1155,17 @@ <string name="attribute_survey_marker_no">Nenà v blÃzkosti měřiÄské znaÄky</string> <string name="attribute_offset_cache_yes">Offset keÅ¡</string> <string name="attribute_offset_cache_no">Nenà to Offset keÅ¡</string> - <string name="quote">UÄinit Geocaching lehÄà a uživatelé lÃnÄ›jÅ¡Ã.</string> + <string name="quote">UÄinit Geocaching lehÄà a uživatele lÃnÄ›jÅ¡Ã.</string> <string name="powered_by">carnero</string> - <string name="support">Podpora: <a href="">support@cgeo.org</a></string> - <string name="website">Stránka: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">Stránka c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo na Google Play</a></string> + <string name="support_title">Podpora</string> + <string name="website_title">Webové stránky</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">stránka c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo na Google Play</a></string> <string name="about_twitter">Má <b>c:geo</b> publikovat nový status na Twitteru vždy, když zalogujeÅ¡ keÅ¡?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Dostupné nové vydánÃ.\nKlepni pro instalaci.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Dostupné nové \"noÄnà sestavenÃ\"\nKlepni pro instalaci.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Dostupný nový kandidát na vydánÃ.\nKlepni pro instalaci.</string> @@ -1140,13 +1180,43 @@ <string name="tts_stopped">ŘeÄ ukonÄena</string> <string name="err_tts_lang_not_supported">PÅ™evod textu na Å™eÄ nenà pro tento jazyk k dispozici.</string> <string name="tts_one_kilometer">jeden kilometr</string> + <plurals name="tts_kilometers"> + <item quantity="one">%s kilometr</item> + <item quantity="few">%s kilometry</item> + <item quantity="other">%s kilometrů</item> + </plurals> <string name="tts_one_meter">jeden metr</string> + <plurals name="tts_meters"> + <item quantity="one">%s metr</item> + <item quantity="few">%s metry</item> + <item quantity="other">%s metrů</item> + </plurals> <string name="tts_one_mile">jedna mÃle</string> + <plurals name="tts_miles"> + <item quantity="one">%s mÃle</item> + <item quantity="few">%s mÃle</item> + <item quantity="other">%s mil</item> + </plurals> <string name="tts_one_foot">jedna stopa</string> + <plurals name="tts_feet"> + <item quantity="one">%s stopa</item> + <item quantity="few">%s stopy</item> + <item quantity="other">%s stop</item> + </plurals> <string name="tts_one_oclock">jedna hodina</string> <string name="tts_oclock">%s hodin</string> <string name="clipboard_copy_ok">ZkopÃrováno do schránky</string> - <string name="percent_favorite_points">%\ oblÃbené</string> + <plurals name="days_ago"> + <item quantity="one">vÄera</item> + <item quantity="few">pÅ™ed %d dny</item> + <item quantity="other">pÅ™ed %d dny</item> + </plurals> + <plurals name="favorite_points"> + <item quantity="one">%s oblÃbená</item> + <item quantity="few">%s oblÃbené</item> + <item quantity="other">%s oblÃbených</item> + </plurals> + <string name="more_than_percent_favorite_points">> %d%% oblÃbených položek</string> <string name="cgeo_shortcut">c:geo zástupce</string> <string name="create_shortcut">VytvoÅ™it zástupce</string> <string name="send">Odeslat</string> @@ -1156,6 +1226,8 @@ <string name="showcase_main_text">c:geo nynà umÃsÅ¥uje položky menu v záhlavà jako ostatnà modernà aplikace. NÄ›které položky jsou skryty za symbolem třà teÄek. Dlouhým stiskem tlaÄÃtka zobrazÃÅ¡ jeho popis.</string> <string name="showcase_cachelist_title">PÅ™epÃnánà seznamů</string> <string name="showcase_cachelist_text">Mezi seznamy s keÅ¡kami můžeÅ¡ pÅ™epÃnat klepnutÃm na název seznamu.</string> + <string name="showcase_compass_hint_title">Zobrazit nápovÄ›du</string> + <string name="showcase_compass_hint_text">Tato nová položka vám může poradit, kde keÅ¡ku hledat - zobrazuje nápovÄ›du, pokud je k dispozici.</string> <string name="confirm_log_title">Neobvyklý typ logu</string> <string name="confirm_log_message">Opravdu chceÅ¡ zalogovat „%s“?</string> </resources> diff --git a/main/res/values-da/strings.xml b/main/res/values-da/strings.xml index 5f4a061..7939498 100644 --- a/main/res/values-da/strings.xml +++ b/main/res/values-da/strings.xml @@ -9,8 +9,8 @@ <string name="about">Om c:geo</string> <string name="latitude">Breddegrad</string> <string name="longitude">Længdegrad</string> - <string name="settings_titlebar">c:geo Indstillinger</string> - <string name="all_types">Alle Cache typer</string> + <string name="settings_titlebar">c:geo indstillinger</string> + <string name="all_types">Alle cachetyper</string> <string name="traditional">Traditionel cache</string> <string name="multi">Multi-cache</string> <string name="mystery">Ukendt cache</string> @@ -71,15 +71,17 @@ <string name="log_retractlisting">Retract Listing</string> <string name="log_marked_missing">Markeret som mangler</string> <string name="log_tb_nothing">Gør intet</string> - <string name="log_tb_visit">Besøg</string> + <string name="log_tb_visit">Besøgt</string> <string name="log_tb_drop">Læg her</string> <string name="log_tb_changeall">Ændr alle</string> - <string name="log_save">Gem</string> + <string name="log_save">Gem offline</string> <string name="log_saving">Sender logbesked…</string> <string name="log_saving_and_uploading">Sender logbesked og billede…</string> <string name="log_clear">Fjern</string> <string name="log_post_not_possible">Indlæser logside…</string> + <string name="log_date_future_not_allowed">Logdatoer, der ligger i fremtiden, er ikke tilladt.</string> <string name="log_add">Tilføj</string> + <string name="log_repeat">Gentag sidste logbesked</string> <string name="log_no_rating">Ingen vurdering</string> <string name="log_stars_1_description">DÃ¥rlig</string> <string name="log_stars_15_description">Temmelig dÃ¥rlig</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Adgangskode til log:</string> <string name="log_hint_log_password">Skriv adgangskode til log</string> <string name="log_oc_team_comment">OC Hold-meddelelse</string> + <string name="log_your_saved_log">Dine gemte log</string> <string-array name="log_image_scales"> <item>Ingen skalering</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Loginoplysninger mangler</string> <string name="err_login_failed_toast">c:geo kan ikke logge ind. c:geo fungerer offline med gemte cacher. Kontrollér login-indstillingerne eller aktivér din Internetforbindelse.</string> <string name="err_unknown">Ukendt fejl</string> + <string name="err_unknown_address">c:geo kunne ikke tilknytte denne adresse til en eksisterende placering</string> <string name="err_comm">Ukendt forbindelsesfejl</string> <string name="err_missing_auth">Intet brugernavn og/eller password konfigureret.</string> <string name="err_wrong">Fejl i login</string> @@ -132,10 +136,10 @@ <string name="err_unvalidated_account">Du skal først validere din konto pÃ¥ geocaching.com.</string> <string name="err_unpublished">Den forespurgte cache er ikke frigivet.</string> <string name="err_premium_only">Denne cache er kun tilgængelig for Geocaching.com Premium-medlemmer.</string> - <string name="err_detail_open">Beklager, c:geo kan ikke indlæse cachedetaljer.</string> + <string name="err_detail_open">c:geo kan ikke indlæse cachedetaljer.</string> <string name="err_detail_cache">Beklager, c:geo kan ikke vise denne cache.</string> - <string name="err_detail_cache_find">Beklager, c:geo kan ikke vise denne cache</string> - <string name="err_detail_cache_find_some">Beklager, c:geo kan ikke vise denne cache.</string> + <string name="err_detail_cache_find">c:geo kan ikke finde geocachen</string> + <string name="err_detail_cache_find_some">c:geo kan ikke finde denne denne geocache.</string> <string name="err_detail_cache_find_any">c:geo kan ikke finde nogen geocacher.</string> <string name="err_detail_google_maps_limit_reached">c: geo kunne ikke hente statisk kort. MÃ¥ske er det tilladte maksimum for Google Maps API forespørgsler overskredet.</string> <string name="err_detail_no_spoiler">c:geo fandt ingen spoilerbilleder til denne cache.</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Optagelse af et billede mislykkedes.</string> <string name="err_tb_display">c:geo kan ikke vise den forespurgte Trackable. Er det virkelig en Trackable?</string> <string name="err_tb_details_open">c:geo kan ikke Ã¥bne Trackable-detaljer.</string> - <string name="err_tb_forgot_saw">c:geo glemte hvilken Trackable du sÃ¥.</string> <string name="err_tb_find">c:geo kan ikke finde den forespurgte Trackable</string> <string name="err_tb_find_that">c:geo kan ikke finde den forespurgte Trackable.</string> <string name="err_waypoint_cache_unknown">c: geo ved ikke hvilken cache, du ønsker at tilføje et waypoint til.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c: geo kan ikke bestemme din placering.</string> <string name="err_point_no_position_given_title">Oplysninger mangler</string> <string name="err_point_no_position_given">Udfyld mindst breddegrad og længdegrad eller afstand og pejling. Du kan ogsÃ¥ udfylde alle fire felter.</string> - <string name="err_point_curr_position_unavailable">c: geo har endnu ikke bestemt din position. Vent venligst…</string> <string name="err_point_bear_and_dist_title">Har du brug for hjælp?</string> <string name="err_point_bear_and_dist">Udfyld bÃ¥de pejling og afstand. Pejlingen er en kompasvinkel mellem 0 og 360 grader i forhold til nord. Afstanden kræver ikke enheder.</string> <string name="err_log_load_data">c: geo kan ikke indlæse de data, der kræves for at logge besøget.</string> <string name="err_log_load_data_again">c: geo kan ikke indlæse de data, der kræves for at logge besøget. Forsøger igen.</string> <string name="err_log_load_data_still">c:geo forsøger stadig at indlæse de data, som kræves for at sende logbeskeden. Vent venligst.</string> - <string name="err_log_post_failed">Din logbesked blev muligvis ikke blev gemt korrekt. Kontrollér venligst pÃ¥ geocaching.com.</string> - <string name="err_log_post_failed_ec">Din logbesked blev muligvis ikke blev gemt korrekt. Kontrollér venligst pÃ¥ extremecaching.com.</string> - <string name="err_logimage_post_failed">Dit logbeskedbillede blev muligvis ikke gemt korrekt. Kontrollér venligst pÃ¥ geocaching.com.</string> + <string name="err_log_post_failed">Din logbesked blev muligvis ikke uploadet. Kontrollér logbeskeden pÃ¥ geocachens hjemmeside.</string> + <string name="err_logimage_post_failed">Dit logbillede blev muligvis ikke uploadet korrekt. Kontrollér billedet pÃ¥ geocachens hjemmeside.</string> <string name="err_search_address_forgot">c: geo glemte den adresse, du forsøgte at finde.</string> <string name="err_parse_lat">c:geo kan ikke forstÃ¥ den indtastede breddegrad.</string> <string name="err_parse_lon">c:geo kan ikke forstÃ¥ den indtastede længdegrad.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Netværk</string> <string name="loc_fused">Kombineret</string> <string name="loc_low_power">Lavt strømforbrug</string> + <string name="loc_home">Hjemmeposition</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Bestemmer position</string> @@ -263,15 +265,18 @@ <string name="caches_sort_finds">Fund</string> <string name="caches_sort_state">Status</string> <string name="caches_sort_storage">Dato for lagring pÃ¥ enhed</string> + <string name="caches_sort_eventdate">Eventdato</string> <string name="caches_select_mode">Markér</string> <string name="caches_select_mode_exit">Afslut markering</string> <string name="caches_select_invert">Omvend markering</string> <string name="caches_nearby">I nærheden</string> <string name="caches_manage">Administrér</string> <string name="caches_remove_all">Fjern alle</string> - <string name="caches_remove_all_confirm">Vil du fjerne alle %s cacher fra den aktuelle liste?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Vil du fjerne denne cache fra den aktuelle liste?</item> + <item quantity="other">Ønsker du at fjerne alle %d cacher fra den aktuelle liste?</item> + </plurals> <string name="caches_remove_selected">Fjern valgte</string> - <string name="caches_remove_selected_confirm">Vil du fjerne de valgte %s cacher fra din enhed?</string> <string name="caches_remove_progress">Fjerner cacher</string> <string name="caches_delete_events">Slet tidligere begivenheder</string> <string name="caches_refresh_selected">Genindlæs valgte</string> @@ -291,13 +296,18 @@ <string name="caches_filter_track">Med Trackables</string> <string name="caches_filter_clear">Nulstil filtre</string> <string name="caches_filter_modified">Med ændret position</string> + <string name="caches_filter_offline_log">Med offline log</string> <string name="caches_filter_origin">Kilde</string> <string name="caches_filter_distance">Afstand</string> <string name="caches_filter_personal_note">Med personlig note</string> <string name="caches_filter_popularity">Favoritter</string> <string name="caches_filter_popularity_ratio">Favoritter [%]</string> + <string name="caches_filter_personal_data">Med personlige data</string> + <string name="caches_filter_rating">Med vurdering</string> + <string name="caches_filter_own_rating">Med egen vurdering</string> <string name="caches_removing_from_history">Fjerner fra historik…</string> <string name="caches_clear_offlinelogs">Fjern offline logbeskeder</string> + <string name="caches_clear_offlinelogs_message">Vil du fjerne offline logbeskeder?</string> <string name="caches_clear_offlinelogs_progress">Fjerner offline logbeskeder</string> <string name="list_menu_create">Opret ny liste</string> <string name="list_menu_drop">Fjern aktuelle liste</string> @@ -320,13 +330,17 @@ <string name="list_not_available">Listen er ikke længere tilgængelig, skifter til standard liste</string> <string name="about_version">Version</string> <string name="about_changelog">Ændringslog</string> + <string name="about_system">System</string> <string name="about_donate">Donér</string> <string name="about_donation_more">Donér\nudvikling</string> <string name="about_contributors">Bidragsydere</string> <string name="about_license">Licens</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Hjælp</string> + <string name="about_system_include">Vedhæft følgende systemoplysninger nÃ¥r du sender en fejlrapport eller beder om yderligere oplysninger om c:geo:</string> + <string name="changelog_github">Liste over alle ændringer</string> <string name="settings_title_services">Tjenester</string> + <string name="settings_summary_services">Konfigurér oplysninger om brugerkonto og adgang til valgfrie tjenester.</string> <string name="settings_title_appearance">Udseende</string> <string name="settings_title_cachedetails">Cachedetaljer</string> <string name="settings_title_offlinedata">Offline data</string> @@ -364,6 +378,9 @@ <string name="settings_activate_oc_uk">Aktivér</string> <string name="init_oc_uk_description">Giv c:geo tilladelse til at søge efter cacher samt tilgÃ¥ og filtrere dine fundne cacher pÃ¥ opencaching.org.uk.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">For at kunne bedømme en cache skal du følge instruktionerne pÃ¥ GCVote.com og angive dit password til GCVote her.</string> + <string name="err_gcvote_send_rating">Fejl under afsendelse af bedømmelse. Kontrollér eller fjern GCVote password under Indstillinger.</string> + <string name="gcvote_sent">Stemme blev afsendt</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktivér</string> <string name="init_username">Brugernavn</string> @@ -434,6 +451,8 @@ <string name="init_backup_success">Database blev kopieret til:</string> <string name="init_backup_failed">Backup af database fejlede.</string> <string name="init_backup_unnecessary">Databasen er tom og det er ikke nødvendigt at tage backup.</string> + <string name="backup_confirm_overwrite">Vil du overskrive den eksisterende backup fra %s?</string> + <string name="restore_confirm_overwrite">Vil du overskrive %s pÃ¥ din enhed med denne backup?</string> <string name="init_restore_success">Gendannelse fuldført.</string> <string name="init_restore_failed">Gendannelse fejlede.</string> <string name="init_restore_running">Gendanner cache-database…</string> @@ -590,6 +609,7 @@ </plurals> <string name="cache_waypoints_add">Tilføj waypoint</string> <string name="cache_hint">Hint</string> + <string name="cache_hint_not_available">Intet hint tilgængeligt</string> <string name="cache_logs">Logbog</string> <string name="cache_logs_friends_and_own">Venners/egne logbeskeder</string> <string name="cache_dialog_loading_details">Indlæser cachedetaljer…</string> @@ -629,9 +649,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Ã…bn i browser</string> <string name="cache_menu_visit">Log besøg</string> - <string name="cache_menu_visit_offline">Log besøg offline</string> + <string name="cache_menu_visit_offline">Hurtig offline logbesked</string> <string name="cache_menu_spoilers">Spoilerbilleder</string> <string name="cache_menu_around">Cacher i nærheden</string> + <string name="around">I nærheden af %s</string> <string name="cache_menu_event">Tilføj til kalender</string> <string name="cache_menu_details">Detaljer</string> <string name="cache_menu_refresh">Genindlæs</string> @@ -640,6 +661,9 @@ <string name="cache_menu_whereyougo">WhereYouGo</string> <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Stem</string> + <string name="cache_menu_checker">Ã…ben Geochecker</string> + <string name="cache_menu_ignore">Ignorér cache</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Log gemt</string> <string name="cache_status_found">Fundet</string> @@ -725,6 +749,7 @@ <string name="waypoint_note">Note</string> <string name="waypoint_visited">Besøgt</string> <string name="waypoint_save">Gem</string> + <string name="waypoint_cancel_edit">Annullér</string> <string name="waypoint_loading">Indlæser waypoint…</string> <string name="waypoint_do_not_touch_cache_coordinates">Ingen ændringer i cacheposition</string> <string name="waypoint_set_as_cache_coords">Sæt som cacheposition i c:geo</string> @@ -749,6 +774,8 @@ <string name="search_clear_history">Slet historik</string> <string name="search_history_cleared">Historik slettet</string> <string name="waypoint_coordinate_formats_plain">Simpel</string> + <string name="from_clipboard">Fra udklipsholder</string> + <string name="copy_to_clipboard">Kopiér til upklipsholder</string> <string name="visit_tweet">Post fund pÃ¥ Twitter</string> <string name="map_map">Kort</string> <string name="map_live">Live-kort</string> @@ -853,7 +880,7 @@ <string name="helper_contacts_description">Giver dig mulighed for at Ã¥bne kontaktside (fra dine kontakter) direkte fra en logbesked, sÃ¥ du let kan kontakte dine venner.</string> <string name="helper_sendtocgeo_description">Send2c:geo (send til c:geo) er en browserudvidelse <strong>til din PC</strong>. Med send2c:geo kan du sende cacher direkte fra din browser til c:geo pÃ¥ din Android-enhed ved blot at klikke pÃ¥ en knap i din browser.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Simpel og brugervenlig app, som viser online kort og giver dig mulighed for at downloade dem direkte til offline tilstand (gælder kun raster-kort). Understøtter ogsÃ¥ optagelse af GPS-spor, administration af interessepunkter og mange andre anvendelige funktioner.</string> + <string name="helper_locus_description">Udendørs navigationsapp til din telefon eller tablet. Vis topografiske kort offline, track din rute, find geocacher, brug stemmeguide og meget mere.</string> <string name="helper_gpsstatus_title">GPS-status</string> <string name="helper_gpsstatus_description">Du kan bruger radaren i denne app sammen med c:geo. Appen giver desuden en mængde GPS-relateret information.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -933,7 +960,7 @@ <string name="attribute_abandonedbuilding_no">Ikke forladt bygning</string> <string name="attribute_hike_short_yes">Kort gÃ¥tur (under 1 km)</string> <string name="attribute_hike_short_no">Ikke kort gÃ¥tur</string> - <string name="attribute_hike_med_yes">Mellemlang gÃ¥tur (1-10 km)</string> + <string name="attribute_hike_med_yes">Mellemlang gÃ¥tur (1–10 km)</string> <string name="attribute_hike_med_no">Ikke mellemlang gÃ¥tur</string> <string name="attribute_hike_long_yes">Lang gÃ¥tur (over 10 km)</string> <string name="attribute_hike_long_no">Ikke lang gÃ¥tur</string> @@ -1104,12 +1131,15 @@ <string name="attribute_offset_cache_yes">Offset-cache</string> <string name="attribute_offset_cache_no">Ikke en offset-cache</string> <string name="quote">To make geocaching easier, to make users lazier.</string> - <string name="support">Support: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string> - <string name="website">Hjemmeside: <a href="http://cgeo.org/">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string> - <string name="twitter">Twitter: <a href="http://twitter.com/android_gc">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo pÃ¥ Google Play</a></string> + <string name="support_title">Support</string> + <string name="website_title">Websted</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">c:geo webside</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo pÃ¥ Google Play</a></string> <string name="about_twitter">Skal <b>c:geo</b> sende status til Twitter hver gang du logger en cache?</string> + <string name="faq_title">Ofte stillede spørgsmÃ¥l</string> <string name="status_new_release" tools:ignore="UnusedResources">Ny udgave er tilgængelig.\nKlik for at installere.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nyt nightly build af c:geo er tilgængelig.\nKlik for at installere.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Ny release kandidat af c:geo er tilgængelig.\nKlik for at installere.</string> @@ -1150,7 +1180,7 @@ <item quantity="one">%s favorit</item> <item quantity="other">%s favoritter</item> </plurals> - <string name="percent_favorite_points">%% favoritter</string> + <string name="more_than_percent_favorite_points">> %d%% favoritter</string> <string name="cgeo_shortcut">c:geo genvej</string> <string name="create_shortcut">Opret genvej</string> <string name="send">Send</string> @@ -1160,6 +1190,8 @@ <string name="showcase_main_text">Som i andre moderne apps er menupunkter i c:geo nu placeret i titellinien. Nogle menupunkter er skjult og bliver først vist nÃ¥r du trykker pÃ¥ knappen med tre prikker. Et langt tryk pÃ¥ et menupunkt Ã¥bner en beskrivelse af menupunktet.</string> <string name="showcase_cachelist_title">Skift af liste</string> <string name="showcase_cachelist_text">Du kan skifte mellem dine lister ved at trykke pÃ¥ listens titel.</string> + <string name="showcase_compass_hint_title">Vis tip</string> + <string name="showcase_compass_hint_text">Dette nye menupunkt kan give dig en idé om hvor man kan finde cachen - det viser tippet, hvis det er tilgængelig.</string> <string name="confirm_log_title">Usædvanlig logtype</string> <string name="confirm_log_message">Du er ved at logge \"%s\". Er du sikker?</string> </resources> diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index f764e94..d2c4078 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -74,12 +74,19 @@ <string name="log_tb_visit">Besucht</string> <string name="log_tb_drop">Abgelegt</string> <string name="log_tb_changeall">Alle ändern</string> - <string name="log_save">Speichern</string> + <string name="log_tb_grabbed">Woanders mitgenommen</string> + <string name="log_tb_note">Notiz</string> + <string name="log_tb_discovered">Gesehen</string> + <string name="log_tb_archived">Archiviert</string> + <string name="log_save">Offline speichern</string> <string name="log_saving">Log wird gesendet…</string> <string name="log_saving_and_uploading">Log und Bild werden gesendet…</string> <string name="log_clear">Leeren</string> <string name="log_post_not_possible">Lade Log-Seite…</string> + <string name="log_post_geocode_missing">Geocode fehlt…</string> + <string name="log_date_future_not_allowed">Logs in der Zukunft sind nicht erlaubt.</string> <string name="log_add">Hinzufügen</string> + <string name="log_repeat">Verwende das letzte Log erneut</string> <string name="log_no_rating">Keine Bewertung</string> <string name="log_stars_1_description">Schlecht</string> <string name="log_stars_15_description">Lohnt sich nicht</string> @@ -107,6 +114,7 @@ <string name="log_password_title">Log-Passwort:</string> <string name="log_hint_log_password">Log-Passwort eingeben</string> <string name="log_oc_team_comment">OC Team Bemerkung</string> + <string name="log_your_saved_log">Dein gespeichertes Log</string> <string-array name="log_image_scales"> <item>Keine Skalierung</item> <item>512 px</item> @@ -120,13 +128,15 @@ <string name="err_none">OK</string> <string name="err_parse">Parsing der Anmeldung gescheitert</string> <string name="err_server">Verbindung zu Geocaching.com konnte nicht hergestellt werden (Server oder Verbindung inaktiv?)</string> - <string name="err_server_ec">Verbindung zu Extremcaching.com konnte nicht hergestellt werden (Server oder Verbindung inaktiv?)</string> + <string name="err_server_ec">Verbindung zu extremcaching.com konnte nicht hergestellt werden. Server ist nicht verfügbar oder keine Internet-Verbindung vorhanden.</string> + <string name="err_server_gk">Verbindung zu geokrety.org konnte nicht hergestellt werden. Server ist nicht verfügbar oder keine Internet-Verbindung vorhanden.</string> <string name="err_login">Keine Anmeldedaten gespeichert.</string> <string name="err_login_failed_toast">c:geo konnte sich nicht einloggen und arbeitet im Offline-Modus. Bitte die Login-Daten in den Einstellungen überprüfen oder eine Internetverbindung herstellen.</string> <string name="err_unknown">Unbekannter Fehler</string> + <string name="err_unknown_address">c:geo konnte keine Koordinaten für diese Adresse ermitteln</string> <string name="err_comm">Unbekannter Kommunikationsfehler</string> <string name="err_missing_auth">Benutzername oder Passwort nicht gesetzt.</string> - <string name="err_wrong">Falsche Anmeldedaten</string> + <string name="err_wrong">Benutzername und/oder Passwort falsch</string> <string name="err_maintenance">Geocaching.com wird zur Zeit gewartet, bitte später erneut versuchen. c:geo arbeitet im Offline-Modus.</string> <string name="err_license">Die Geocaching.com Nutzungsbedingungen wurden nicht akzeptiert. c:geo kann deshalb keine Koordinaten laden.</string> <string name="err_unvalidated_account">Die Logindaten müssen zuerst auf Geocaching.com validiert werden.</string> @@ -158,7 +168,7 @@ <string name="err_acquire_image_failed">Erstellen eines Fotos ist fehlgeschlagen.</string> <string name="err_tb_display">c:geo kann den gewünschten Trackable nicht anzeigen. Ist es wirklich einer?</string> <string name="err_tb_details_open">c:geo konnte die Details des Trackables nicht öffnen.</string> - <string name="err_tb_forgot_saw">c:geo hat vergessen, welcher Trackable gesehen wurde.</string> + <string name="err_tb_not_loggable">Dieser Trackable ist nicht logbar.</string> <string name="err_tb_find">c:geo findet den Trackable nicht</string> <string name="err_tb_find_that">c:geo konnte diesen Trackable nicht finden.</string> <string name="err_waypoint_cache_unknown">c:geo weiß nicht, zu welchem Cache der Wegpunkt hinzugefügt werden soll.</string> @@ -166,15 +176,17 @@ <string name="err_point_unknown_position">c:geo konnte den aktuellen Standort nicht bestimmen.</string> <string name="err_point_no_position_given_title">Info benötigt</string> <string name="err_point_no_position_given">Mindestens Längen- und Breitengrad oder Entfernung und Richtung angeben. Auch alle Angaben sind möglich.</string> - <string name="err_point_curr_position_unavailable">c:geo hat noch keine aktuelle Koordinaten. Bitte einen Moment warten…</string> <string name="err_point_bear_and_dist_title">Hilfe benötigt?</string> <string name="err_point_bear_and_dist">Angaben zu Richtung und Entfernung sind notwendig. Richtung: 0 bis 360 Grad relativ zum Norden. Die Entfernung benötigt keine Bezeichnung der Einheiten. </string> <string name="err_log_load_data">c:geo konnte die benötigten Daten nicht laden, um den Besuch zu loggen.</string> <string name="err_log_load_data_again">c:geo konnte die benötigten Daten nicht laden, um den Besuch zu loggen. Bitte erneut versuchen.</string> <string name="err_log_load_data_still">c:geo lädt gerade die benötigten Daten. Bitte kurz warten.</string> - <string name="err_log_post_failed">c:geo konnte den Log nicht absenden. Bitte auf geocaching.com überprüfen.</string> + <string name="err_log_post_missing_tracking_code">Tracking-Code fehlt.</string> + <string name="err_log_post_missing_coordinates">Koordinaten fehlen.</string> + <string name="err_log_post_failed">Der Log-Eintrag wurde scheinbar nicht gesendet. Bitte auf der betreffenden Geocaching-Webseite prüfen.</string> <string name="err_log_post_failed_ec">c:geo konnte den Log nicht absenden. Bitte auf Extremcaching.com überprüfen.</string> - <string name="err_logimage_post_failed">Es scheint dass Ihr Logfoto nicht hochgeladen werden konnte. Bitte prüfen Sie es auf Geocaching.com nach.</string> + <string name="err_log_post_failed_gk">c:geo konnte den Log nicht absenden. Bitte auf GeoKrety.org überprüfen.</string> + <string name="err_logimage_post_failed">Das Log-Bild wurde scheinbar nicht hochgeladen. Bitte auf der betreffenden Geocaching-Webseite prüfen.</string> <string name="err_search_address_forgot">c:geo hat die Adresse vergessen, die gesucht wurde.</string> <string name="err_parse_lat">c:geo konnte den Breitengrad nicht verarbeiten.</string> <string name="err_parse_lon">c:geo konnte den Längengrad nicht verarbeiten.</string> @@ -211,6 +223,7 @@ <string name="loc_net">Netzwerk</string> <string name="loc_fused">Kombiniert</string> <string name="loc_low_power">Energiesparmodus</string> + <string name="loc_home">Heimkoordinaten</string> <string name="loc_gps">GPS</string> <string name="loc_sat">SAT</string> <string name="loc_trying">Lokalisierung</string> @@ -229,7 +242,7 @@ <string name="caches_nearby_button">In der Nähe</string> <string name="advanced_search_button">Suche</string> <string name="stored_caches_button">Gespeichert</string> - <string name="any_button">Ãœberall</string> + <string name="any_button">Gehe zu</string> <string name="unknown_scan">Konnte keinen Geocode im Scan finden.</string> <string name="caches_no_cache">Kein Cache</string> <string name="caches_more_caches">Mehr Caches laden</string> @@ -263,15 +276,22 @@ <string name="caches_sort_finds">Funde</string> <string name="caches_sort_state">Status</string> <string name="caches_sort_storage">Speicherdatum</string> + <string name="caches_sort_eventdate">Event-Datum</string> <string name="caches_select_mode">Auswahlmodus</string> <string name="caches_select_mode_exit">Auswahlmodus beenden</string> <string name="caches_select_invert">Auswahl invertieren</string> <string name="caches_nearby">In der Nähe</string> <string name="caches_manage">Verwalten</string> <string name="caches_remove_all">Alle löschen</string> - <string name="caches_remove_all_confirm">Sollen alle %s Caches gelöscht werden?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Soll der Cache von dieser Liste gelöscht werden?</item> + <item quantity="other">Sollen alle %d Caches von dieser Liste gelöscht werden?</item> + </plurals> <string name="caches_remove_selected">Ausgewählte löschen</string> - <string name="caches_remove_selected_confirm">Sollen die %s Caches gelöscht werden?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Soll dieser Cache gelöscht werden?</item> + <item quantity="other">Sollen die %d ausgewählten Caches gelöscht werden?</item> + </plurals> <string name="caches_remove_progress">Entferne Caches…</string> <string name="caches_delete_events">Vergangene Events löschen</string> <string name="caches_refresh_selected">Ausgewählte aktualisieren</string> @@ -291,13 +311,18 @@ <string name="caches_filter_track">Mit Trackables</string> <string name="caches_filter_clear">Filter zurücksetzen</string> <string name="caches_filter_modified">Mit geänderten Koordinaten</string> + <string name="caches_filter_offline_log">Mit Offline-Log</string> <string name="caches_filter_origin">Herkunft</string> <string name="caches_filter_distance">Entfernung</string> <string name="caches_filter_personal_note">Mit persönlicher Notiz</string> <string name="caches_filter_popularity">Favoriten</string> <string name="caches_filter_popularity_ratio">Favoriten [%]</string> + <string name="caches_filter_personal_data">Mit eigenen Informationen</string> + <string name="caches_filter_rating">Mit Bewertung</string> + <string name="caches_filter_own_rating">Mit eigener Bewertung</string> <string name="caches_removing_from_history">Lösche aus Verlauf…</string> <string name="caches_clear_offlinelogs">Offline-Logs löschen</string> + <string name="caches_clear_offlinelogs_message">Möchtest du die Offline-Logs löschen?</string> <string name="caches_clear_offlinelogs_progress">Lösche Offline-Logs</string> <string name="list_menu_create">Neue Liste</string> <string name="list_menu_drop">Aktuelle Liste löschen</string> @@ -320,13 +345,17 @@ <string name="list_not_available">Liste nicht mehr vorhanden, wechsele zur Standardliste</string> <string name="about_version">Version</string> <string name="about_changelog">Änderungen</string> + <string name="about_system">System</string> <string name="about_donate">Spenden</string> <string name="about_donation_more">Spenden für\nEntwicklung</string> <string name="about_contributors">Mitwirkende</string> <string name="about_license">Lizenz</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Hilfe</string> + <string name="about_system_include">Bitte die folgende Systeminformation bei jedem Fehlerbericht oder bei Informationsanfragen zu c:geo mitsenden:</string> + <string name="changelog_github">Liste aller Änderungen</string> <string name="settings_title_services">Dienste</string> + <string name="settings_summary_services">Konfiguriere Zugangsdaten und den Zugriff auf optionale Dienste.</string> <string name="settings_title_appearance">Erscheinungsbild</string> <string name="settings_title_cachedetails">Cache-Details</string> <string name="settings_title_offlinedata">Offline-Daten</string> @@ -370,9 +399,13 @@ <string name="init_oc_ro">Opencaching.ro</string> <string name="settings_activate_oc_ro">Aktivieren</string> <string name="init_oc_ro_description">Autorisiere c:geo auf opencaching.ro zuzugreifen um Caches zu suchen und nach deinen Funden zu filtern.</string> + <string name="init_oc_uk">Opencaching.org.uk</string> <string name="settings_activate_oc_uk">Aktivieren</string> <string name="init_oc_uk_description">Autorisiere c:geo auf opencaching.org.uk zuzugreifen um Caches zu suchen und nach deinen Funden zu filtern.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Um einen Cache bewerten zu können, folge der Anleitung auf gcvote.com und gib das GCVote-Passwort anschließend hier ein.</string> + <string name="err_gcvote_send_rating">Fehler beim Senden der Bewertung. Prüfe das GCVote-Passwort in den Einstellungen oder lösche es.</string> + <string name="gcvote_sent">Bewertung erfolgreich gesendet</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktivieren</string> <string name="init_username">Benutzername</string> @@ -443,6 +476,8 @@ <string name="init_backup_success">Datenbank von c:geo wurde erfolgreich kopiert nach:</string> <string name="init_backup_failed">Sicherung der Datenbank von c:geo fehlgeschlagen.</string> <string name="init_backup_unnecessary">Datenbank ist leer, keine Sicherung notwendig.</string> + <string name="backup_confirm_overwrite">Möchtest du das existierende Backup vom %s überschreiben?</string> + <string name="restore_confirm_overwrite">Möchtest du %s auf deinem Gerät mit dem Backup überschreiben?</string> <string name="init_restore_success">Wiederherstellung fertig.</string> <string name="init_restore_failed">Wiederherstellung fehlgeschlagen.</string> <string name="init_restore_running">Wiederherstellung der Cache-Datenbank…</string> @@ -492,8 +527,8 @@ <string name="init_maintenance_directories_note">c:geo speichert Bilder, Log-Bilder und weitere Dateien zu einem Cache in einem separaten Verzeichnis. In manchen Fällen (z.B. bei Sichern und Wiederherstellen der Datenbank) kann dieses Verzeichnis unnötige Daten enthalten, die gelöscht werden können.</string> <string name="init_maintenance_directories">Verwaiste Daten löschen</string> <string name="init_location">Positionierung</string> - <string name="init_location_note">Auf Geräten mit GooglePlay-Diensten kann c:geo automatisch eine bessere Positions-Bestimmung nutzen. Allerdings kann dann kein externer Bluetooth GPS-Empfänger verwendet werden. Weiterhin kann damit ein Energiesparmodus ohne GPS genutzt werden, wenn hohe Genauigkeit nicht unbedingt erforderlich ist.</string> - <string name="init_location_googleplayservices">GooglePlay-Dienst nutzen</string> + <string name="init_location_note">Auf Geräten mit Google Play-Diensten kann c:geo automatisch eine bessere Positions-Bestimmung nutzen. Allerdings kann dann kein externer Bluetooth GPS-Empfänger verwendet werden. Weiterhin kann damit ein Energiesparmodus ohne GPS genutzt werden, wenn hohe Genauigkeit nicht unbedingt erforderlich ist.</string> + <string name="init_location_googleplayservices">Google Play-Dienst nutzen</string> <string name="init_low_power">Energiesparmodus</string> <string name="init_low_power_note">Der Energiesparmodus vermeidet die Verwendung von GPS und Gyroskop, wenn eine hochgenaue Position nicht unbedingt notwendig ist. Nachteil ist eine längere Zeit bis zum GPS-Fix.</string> <string name="init_low_power_mode">Energiesparmodus aktivieren</string> @@ -504,6 +539,8 @@ <string name="init_hardware_acceleration_note">Mittels Hardwarebeschleunigung werden grafische Elemente schneller auf den Bildschirm dargestellt. Jedoch enthält das Android auf manchen Geräten Fehler, die zu verschwommenem Text (meistens bei fettgedruckten Zeichen) führen können. in diesen Fällen sollte die Hardwarebeschleunigung deaktiviert werden.</string> <string name="init_hardware_acceleration">Hardwarebeschleunigung aktivieren</string> <string name="settings_open_website">Webseite öffnen</string> + <string name="settings_open_geokrety_register">Öffne Registrierungs-Seite auf GeoKrety.org</string> + <string name="settings_open_geokretymap_website">Öffne GeokretyMap.org Webseite</string> <string name="settings_settings">Einstellungen</string> <string name="settings_information">Information</string> <string name="settings_twitter_cache_message">Nachricht für gefundenen Cache</string> @@ -549,6 +586,10 @@ <string name="auth_dialog_completed_twitter">c:geo ist nun autorisiert, Tweets bei Twitter zu erstellen.</string> <string name="auth_ocde">opencaching.de</string> <string name="auth_ocpl">opencaching.pl</string> + <string name="auth_ocnl">opencaching.nl</string> + <string name="auth_ocus">opencaching.us</string> + <string name="auth_ocro">opencaching.ro</string> + <string name="auth_ocuk">opencaching.org.uk</string> <string name="auth_dialog_completed_oc">c:geo ist nun autorisiert, Caches zu laden und auf %s zu loggen.</string> <plurals name="cache_counts"> <item quantity="one">Ein Cache</item> @@ -601,6 +642,7 @@ </plurals> <string name="cache_waypoints_add">Wegpunkt hinzufügen</string> <string name="cache_hint">Hinweis</string> + <string name="cache_hint_not_available">Kein Hinweis verfügbar</string> <string name="cache_logs">Logbuch</string> <string name="cache_logs_friends_and_own">Logbuch (Freunde/Eigene)</string> <string name="cache_dialog_loading_details">Lade Cache-Details…</string> @@ -640,9 +682,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Im Browser öffnen</string> <string name="cache_menu_visit">Besuch loggen</string> - <string name="cache_menu_visit_offline">Besuch offline loggen</string> + <string name="cache_menu_visit_offline">Offline loggen</string> <string name="cache_menu_spoilers">Hinweisbild</string> <string name="cache_menu_around">Caches im Umkreis</string> + <string name="around">In der Nähe von %s</string> <string name="cache_menu_event">Zum Kalender hinzufügen</string> <string name="cache_menu_details">Details</string> <string name="cache_menu_refresh">Aktualisieren</string> @@ -652,6 +695,10 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble Smartwatch</string> + <string name="cache_menu_android_wear">Android Wear</string> + <string name="cache_menu_vote">Bewerten</string> + <string name="cache_menu_checker">Öffne Geochecker</string> + <string name="cache_menu_ignore">Cache ignorieren</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Gespeicherter Log</string> <string name="cache_status_found">Gefunden</string> @@ -737,6 +784,7 @@ <string name="waypoint_note">Notiz</string> <string name="waypoint_visited">Besucht</string> <string name="waypoint_save">Speichern</string> + <string name="waypoint_cancel_edit">Abbrechen</string> <string name="waypoint_loading">Lade Wegpunkt…</string> <string name="waypoint_do_not_touch_cache_coordinates">Cache-Koordinaten nicht ändern</string> <string name="waypoint_set_as_cache_coords">Als Cache-Koordinaten lokal setzen</string> @@ -761,6 +809,8 @@ <string name="search_clear_history">Verlauf löschen</string> <string name="search_history_cleared">Verlauf gelöscht</string> <string name="waypoint_coordinate_formats_plain">Schlicht</string> + <string name="from_clipboard">Aus der Zwischenablage</string> + <string name="copy_to_clipboard">In Zwischenablage kopieren</string> <string name="visit_tweet">Diesen Eintrag auf Twitter veröffentlichen</string> <string name="map_map">Karte</string> <string name="map_live">Live-Karte</string> @@ -802,7 +852,7 @@ <string name="search_hbu_prefill">Besitzer</string> <string name="search_hbu_button">Suche mit Besitzername</string> <string name="search_tb">Trackable</string> - <string name="search_tb_hint">Trackingnummer</string> + <string name="search_tb_hint">Tracking-Code</string> <string name="search_tb_button">Suche nach Trackable</string> <string name="search_destination">Ziel</string> <string name="search_direction_rel">Vom aktuellen Standort</string> @@ -819,7 +869,7 @@ <string name="trackable_goal">Derzeitiges Ziel</string> <string name="trackable_details">Ãœber diesen Trackable</string> <string name="trackable_image">Foto</string> - <string name="trackable_code">TB-Code</string> + <string name="trackable_code">Tracking-Code</string> <string name="trackable_name">Name</string> <string name="trackable_type">Typ</string> <string name="trackable_owner">Eigentümer</string> @@ -834,6 +884,9 @@ <string name="trackable_distance">Zurückgelegte Strecke</string> <string name="trackable_touch">Trackable-Aktion</string> <string name="trackable_not_activated">Trackable nicht aktiviert</string> + <string name="trackable_travelbug">Travelbug</string> + <string name="trackable_geokrety">Geokrety</string> + <string name="trackable_swaggie">Swaggie</string> <string name="geokret_type_traditional">Traditionell</string> <string name="geokret_type_book_or_media">Buch oder elektronisches Medium</string> <string name="geokret_type_human">Mensch</string> @@ -865,7 +918,7 @@ <string name="helper_contacts_description">Ermöglicht das direkte Öffnen von Kontakten (aus dem eigenen Adressbuch) von Logeinträgen aus, so dass man Freunde einfacher um Hilfe fragen kann.</string> <string name="helper_sendtocgeo_description">Send to c:geo ist eine Browsererweiterung <strong>für Ihren PC</strong>. Beim Durchsuchen von geocaching.com können Sie Caches mit einem Klick im Browser direkt an Ihr Smartphone übermitteln.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Sehr gute App für Online- und Offline-Karten (nur Rasterkarten) mit vielen weiteren Funktionen wie z. B. Trackaufzeichnung, POIs und vieles mehr.</string> + <string name="helper_locus_description">Outdoor Navigations-App für dein Handy oder Tablet. Verwende topografische Karten offline, zeichne Tracks von deinen Touren auf, suche Geocaches, benutze Sprachführung und vieles mehr.</string> <string name="helper_gpsstatus_title">GPS-Status</string> <string name="helper_gpsstatus_description">Das Radar dieser App kann in c:geo verwendet und zusätzlich viele GPS-bezogene Informationen abgerufen werden.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1117,13 +1170,15 @@ <string name="attribute_offset_cache_no">Kein Offset Cache</string> <string name="quote">Um Geocachen einfacher zu machen, um es Anwendern bequemer zu machen.</string> <string name="powered_by">carnero</string> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Webseite: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo auf Google Play</a></string> + <string name="support_title">Support</string> + <string name="website_title">Webseite</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">Seite von c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo bei Google Play</a></string> <string name="about_twitter">Soll jeder neue Fund auf Twitter veröffentlicht werden, wenn er über <b>c:geo</b> geloggt wird?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQs</string> <string name="status_new_release" tools:ignore="UnusedResources">Neuer Release verfügbar.\nKlicken zum Installieren.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Neuer Nightly Build verfügbar.\nKlicken zum Installieren.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Neuer Release Candidate verfügbar.\nKlicken zum Installieren.</string> @@ -1168,7 +1223,7 @@ <item quantity="one">%s Favorit</item> <item quantity="other">%s Favoriten</item> </plurals> - <string name="percent_favorite_points">% Favoriten</string> + <string name="more_than_percent_favorite_points">> %d%% Favoriten</string> <string name="cgeo_shortcut">c:geo Shortcut</string> <string name="create_shortcut">Shortcut erstellen</string> <string name="send">Senden</string> @@ -1178,6 +1233,21 @@ <string name="showcase_main_text">c:geo nutzt nun die Titelzeile für Menü-Optionen wie in anderen modernen Apps. Einige Menüpunkte sind dabei hinter der Drei-Punkt Schaltfläche versteckt. Ein langer Druck auf eine Schaltfläche zeigt die Bedeutung.</string> <string name="showcase_cachelist_title">Liste wechseln</string> <string name="showcase_cachelist_text">Du kannst zwischen deinen Listen wechseln, indem du auf den Titel der Liste klickst.</string> + <string name="showcase_compass_hint_title">Zeige den Hint</string> + <string name="showcase_compass_hint_text">Diese neue Option könnte dir helfen den Cache zu finden - sie zeigt den Hint an, wenn es einen gibt.</string> <string name="confirm_log_title">Ungewöhnlicher Log-Typ</string> <string name="confirm_log_message">Du möchtest \'%s\' loggen. Bist du dir sicher?</string> + <string name="init_geokrety">Geokrety.org</string> + <string name="init_geokrety_login">EInloggen auf GeoKrety.org</string> + <string name="init_connectorGeokretyActive">Geokrety Trackables</string> + <string name="init_summary_geokrety">Lädt Trackables von Geokrety.org</string> + <string name="init_summary_geokrety_cache">Verbessert die Ladezeit.</string> + <string name="init_summary_geokrety_account">Kein Konto konfiguriert.</string> + <string name="init_summary_geokrety_not_anonymous">Loggen aus c:geo kann nicht anonym erfolgen. Bitte registrieren.</string> + <string name="init_geokrety_register_ok">Login erfolgreich</string> + <string name="init_geokrety_register_fail">Login fehlgeschlagen</string> + <string name="init_geokrety_get_secid">API-Schlüssel abrufen</string> + <string name="init_geokrety_description">Speichere deinen API-SChlüssel in c:geo um das Loggen von GeoKrety zu vereinfachen</string> + <string name="init_geokrety_cache_description">GeokretyMap.org stellt zwischengespeicherte Daten für GeoKrety-Trackables zur Verfügung. Die Daten sind möglichweise nicht auf dem neuesten Stand!\nPositionen: ~30min.\nBeschreibungen: ~24h.</string> + <string name="init_geokrety_cache">Benutze zwischengespeicherte Daten</string> </resources> diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index ef02630..c6c28ff 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -2,45 +2,45 @@ <!--Generated by crowdin.com--> <resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">c:geo</string> - <string name="cache">Escondite</string> - <string name="detail">Detalle</string> + <string name="cache">Caché</string> + <string name="detail">Detalles</string> <string name="search">Buscar</string> - <string name="helpers">¿Qué instalar?</string> + <string name="helpers">Programas útiles</string> <string name="about">Sobre c:geo</string> <string name="latitude">Latitud</string> <string name="longitude">Longitud</string> <string name="settings_titlebar">c:geo Ajustes</string> - <string name="all_types">Todos los escondites</string> - <string name="traditional">Tradicionales</string> - <string name="multi">Multis</string> - <string name="mystery">Desconocidos/Mistery</string> - <string name="letterbox">Buzón hÃbrido</string> - <string name="event">Eventos</string> - <string name="mega">Mega-Eventos</string> - <string name="giga">Caché Giga-Evento</string> - <string name="earth">Educativos (Earth)</string> + <string name="all_types">Todos los cachés</string> + <string name="traditional">Tradicional</string> + <string name="multi">Multi</string> + <string name="mystery">Mistery</string> + <string name="letterbox">Letterbox hÃbrido</string> + <string name="event">Evento</string> + <string name="mega">Mega Evento</string> + <string name="giga">Giga Evento</string> + <string name="earth">Earthcaché</string> <string name="cito">Eventos Limpieza(CITO)</string> - <string name="webcam">Webcams</string> - <string name="virtual">Virtuales</string> + <string name="webcam">Webcam</string> + <string name="virtual">Virtual</string> <string name="wherigo">Wherigo</string> - <string name="lostfound">Eventos Perdidos y Encontrados</string> + <string name="lostfound">Evento Lost & Found</string> <string name="ape">Proyecto APE</string> <string name="gchq">Groundspeak HQ</string> - <string name="gps">Exhibición de escondites GPS</string> + <string name="gps">Exhibición de cachés GPS</string> <string name="block">Groundspeak Block Party</string> <string name="unknown">De tipo desconocido</string> - <string name="cache_size_micro">micro</string> - <string name="cache_size_small">pequeño</string> - <string name="cache_size_regular">normal</string> - <string name="cache_size_large">grande</string> - <string name="cache_size_other">otro</string> - <string name="cache_size_virtual">virtual</string> - <string name="cache_size_notchosen">no elegido</string> - <string name="cache_size_unknown">desconocido</string> + <string name="cache_size_micro">Micro</string> + <string name="cache_size_small">Pequeño</string> + <string name="cache_size_regular">Normal</string> + <string name="cache_size_large">Grande</string> + <string name="cache_size_other">Otro</string> + <string name="cache_size_virtual">Virtual</string> + <string name="cache_size_notchosen">No elegido</string> + <string name="cache_size_unknown">Desconocido</string> <string name="cache_size_nano">Nano</string> <string name="cache_size_very_large">Muy grande</string> <string name="wp_final">Ubicación final</string> - <string name="wp_stage">Etapa de multi escondite</string> + <string name="wp_stage">Etapa de un Multicaché</string> <string name="wp_puzzle">Preguntar a contestar</string> <string name="wp_pkg">Zona de aparcamiento</string> <string name="wp_trailhead">Sendero</string> @@ -56,7 +56,7 @@ <string name="log_attended">AsistÃ</string> <string name="log_retrieved">Recogido</string> <string name="log_placed">Depositado</string> - <string name="log_grabbed">Recogido de alguna parte</string> + <string name="log_grabbed">Cogido de otro sitio</string> <string name="log_movecollection">Mover a la colección</string> <string name="log_moveinventory">Mover al inventario</string> <string name="log_maintained">Mantenimiento efectuado</string> @@ -68,18 +68,23 @@ <string name="log_discovered">Descubierto</string> <string name="log_reviewer">Nota del revisor</string> <string name="log_submit_for_review">Enviar para revisión</string> - <string name="log_retractlisting">Retirar ficha del escondite</string> + <string name="log_retractlisting">Retirar ficha</string> <string name="log_marked_missing">Marcado como perdido</string> <string name="log_tb_nothing">No hacer nada</string> <string name="log_tb_visit">Visitado</string> <string name="log_tb_drop">Dejar aquÃ</string> <string name="log_tb_changeall">Cambiar todo</string> - <string name="log_save">Guardar</string> - <string name="log_saving">Enviando registo…</string> + <string name="log_tb_note">Nota</string> + <string name="log_tb_discovered">Descubierto</string> + <string name="log_tb_archived">Archivado</string> + <string name="log_save">Guardar sin conexión</string> + <string name="log_saving">Enviando registro…</string> <string name="log_saving_and_uploading">Enviando registro y subiendo imagen…</string> <string name="log_clear">Limpiar</string> <string name="log_post_not_possible">Cargando página de registro…</string> + <string name="log_date_future_not_allowed">No se permiten registros con fechas futuras.</string> <string name="log_add">Añadir</string> + <string name="log_repeat">Repetir el último registro</string> <string name="log_no_rating">Sin puntuación</string> <string name="log_stars_1_description">malÃsimo</string> <string name="log_stars_15_description">muy malo</string> @@ -107,6 +112,7 @@ <string name="log_password_title">Contraseña:</string> <string name="log_hint_log_password">Introduzca su contraseña</string> <string name="log_oc_team_comment">Comentario equipo OC</string> + <string name="log_your_saved_log">Tu registro guardado</string> <string-array name="log_image_scales"> <item>Sin redimensionar</item> <item>512 px</item> @@ -121,74 +127,78 @@ <string name="err_parse">Error procesando la página de acceso</string> <string name="err_server">Error conectando a Geocaching.com (¿servidor o conexión caidos?)</string> <string name="err_server_ec">Imposible conectar a Extremcaching.com. La página web puede estar caÃda o su conexión a Internet no funciona.</string> + <string name="err_server_gk">No se pudo contactar con Geokrety.org. El sitio web puede estar caÃdo o la conexión a internet no funciona.</string> <string name="err_login">No hay información de acceso guardada</string> - <string name="err_login_failed_toast">c:geo no puede iniciar sesión. c:geo puede funcionar sin conexión con los caches que hayan sido almacenados. Comprueba las opciones de inicio de sesión o active la conexión a internet.</string> + <string name="err_login_failed_toast">c:geo no puede iniciar sesión. c:geo puede funcionar sin conexión con los cachés que hayan sido almacenados. Comprueba las opciones de inicio de sesión o active la conexión a internet.</string> <string name="err_unknown">Error desconocido</string> + <string name="err_unknown_address">c:geo no ha podido ubicar en el mapa esta dirección</string> <string name="err_comm">Error de comunicación desconocido</string> <string name="err_missing_auth">Falta nombre de usuario o contraseña.</string> <string name="err_wrong">Información de acceso errónea</string> <string name="err_maintenance">Geocaching.com no está disponible debido a labores de mantenimiento. c:geo puede funcionar sin conexión con los caches que hayan sido almacenados previamente.</string> - <string name="err_license">El usuario no ha aceptado las condiciones de Geocaching.com license agreement, por lo que c:geo no puede cargar las coordenadas de los escondites.</string> + <string name="err_license">No has aceptado las condiciones del acuerdo de licencia de Geocaching.com, por lo que c:geo no puede cargar las coordenadas de los cachés.</string> <string name="err_unvalidated_account">Antes debe validar su cuenta en la página web Geocaching.com.</string> <string name="err_unpublished">El caché solicitado aún no ha sido publicado.</string> <string name="err_premium_only">Este caché solo está disponible para los miembros Premium de Geocaching.com.</string> - <string name="err_detail_open">Lo siento, c:geo no puede abrir los detalles del escondite.</string> - <string name="err_detail_cache">Lo siento, c:geo no puee mostrar el escondite que quieres. ¿Segur que es un geocache?</string> - <string name="err_detail_cache_find">Lo siento, c:geo no puede encontrar escondites</string> - <string name="err_detail_cache_find_some">Lo siento, c:geo no puede encontrar ese escondite.</string> - <string name="err_detail_cache_find_any">Lo siento, c:geo no puede encontrar algunos escondites.</string> + <string name="err_detail_open">c:geo no puede abrir los detalles del caché.</string> + <string name="err_detail_cache">c:geo no puede mostrar el caché que quieres. ¿Seguro que es un geocaché?</string> + <string name="err_detail_cache_find">c:geo no puede encontrar ningún caché</string> + <string name="err_detail_cache_find_some">c:geo no puede encontrar ese caché.</string> + <string name="err_detail_cache_find_any">c:geo no puede encontrar ningún caché.</string> <string name="err_detail_google_maps_limit_reached">c:geo no ha podido descargar los mapas estáticos. Quizá haya alcanzado el lÃmite de uso del API de Google Maps.</string> - <string name="err_detail_no_spoiler">c:geo no ha encontrado imágenes/pista para este escondite.</string> - <string name="err_detail_no_map_static">c:geo no ha encontrado mapas estáticos para este escondite.</string> - <string name="err_detail_not_load_map_static">Lo siento, c:geo no ha podido cargar mapas estáticos.</string> + <string name="err_detail_no_spoiler">c:geo no ha encontrado imágenes/pista para este caché.</string> + <string name="err_detail_no_map_static">c:geo no ha encontrado mapas estáticos para este caché.</string> + <string name="err_detail_not_load_map_static">c:geo no ha podido cargar los mapas estáticos.</string> <string name="err_detail_still_working">TodavÃa hay otra tarea en ejecución.</string> - <string name="err_watchlist_still_managing">Seguir gestionando tu lista de seguimiento.</string> + <string name="err_watchlist_still_managing">TodavÃa gestionando tu lista de seguimiento.</string> <string name="err_watchlist_failed">Error al cambiar la lista de seguimiento.</string> <string name="err_application_no">c:geo no encuentra ninguna aplicación válida.</string> - <string name="err_auth_initialize">Lo siento, c:geo no ha podido iniciar el proceso de autorización.</string> + <string name="err_auth_initialize">c:geo no ha podido iniciar el proceso de autorización.</string> <string name="err_auth_process">El proceso de autorización ha fallado.</string> - <string name="err_cannot_log_visit">c:geo no tiene información suficiente para registrar la visita. Inténtalo de nuevo con más detalles sobre el escondite.</string> - <string name="err_download_fail">Lo siento, c:geo no ha podido descargar escondites a causa de </string> - <string name="err_dwld_details_failed">Lo siento, c:geo no ha podido descargar los detalles del escondite.</string> - <string name="err_load_descr_failed">Lo siento, c:geo no ha podido cargar la descripción.</string> - <string name="err_location_unknown">c:geo no conoce la ubicación del escondite.</string> + <string name="err_cannot_log_visit">c:geo no puede registrar tu visita. Inténtalo desde la pantalla de detalles del caché.</string> + <string name="err_download_fail">c:geo no ha podido descargar cachés.</string> + <string name="err_dwld_details_failed">c:geo no ha podido descargar los detalles del caché.</string> + <string name="err_load_descr_failed">c:geo no ha podido cargar la descripción.</string> + <string name="err_location_unknown">c:geo no conoce la ubicación del caché.</string> <string name="err_missing_device_name">Debes indicar un nombre de dispositivo antes de registrarte.</string> <string name="err_favorite_failed">Falló el cambio de estado de favorito.</string> <string name="err_select_logimage_failed">No se pudo seleccionar una imagen para el registro.</string> <string name="err_acquire_image_failed">No se pudo obtener una imagen.</string> - <string name="err_tb_display">\"Lo siento, c:geo no puede mostrar el rastreable que buscas. ¿Es realmente rastreable?</string> - <string name="err_tb_details_open">Lo siento, c:geo no puede abrir los detalles del rastreable.</string> - <string name="err_tb_forgot_saw">Lo siento, c:geo ha olvidado qué rastreable has visto.</string> - <string name="err_tb_find">Lo siento, c:geo no encuentra el rasteable</string> - <string name="err_tb_find_that">Lo siento, c:geo no encuentra ese rastreable.</string> - <string name="err_waypoint_cache_unknown">Lo siento, c:geo no sabe a qué escondite quieres añadir un punto de referencia.</string> - <string name="err_waypoint_add_failed">Lo siento, c:geo no ha podido añadir tu punto de referencia.</string> - <string name="err_point_unknown_position">Lo siento, c:geo n puedo identificar donde estás.</string> + <string name="err_tb_display">c:geo no puede mostrar el rastreable que buscas. ¿Es realmente un rastreable?</string> + <string name="err_tb_details_open">c:geo no puede abrir los detalles del rastreable.</string> + <string name="err_tb_not_loggable">Este rastreable no se puede registrar.</string> + <string name="err_tb_find">c:geo no encuentra el rasteable</string> + <string name="err_tb_find_that">c:geo no encuentra ese rastreable.</string> + <string name="err_waypoint_cache_unknown">c:geo no sabe a qué caché quieres añadir un punto de referencia.</string> + <string name="err_waypoint_add_failed">c:geo falló al añadir tu punto de referencia.</string> + <string name="err_point_unknown_position">c:geo no puede reconocer dónde estás.</string> <string name="err_point_no_position_given_title">Información obligatoria</string> <string name="err_point_no_position_given">Rellena como mÃnimo latitud y longitud o distancia y orientación. También puedes rellenar los cuatro campos.</string> - <string name="err_point_curr_position_unavailable">c:geo sigue sin obtener las coordenadas actuales. Espera un poco mas…</string> <string name="err_point_bear_and_dist_title">¿Necesitas ayuda?</string> <string name="err_point_bear_and_dist">Rellena ambos, orientación y distancia. La orientación es un ángulo de 0 a 360 grados relativo al norte. Distancia con o sin unidades.</string> - <string name="err_log_load_data">Lo siento, c:geo no puede cargar los datos necesarios para registrar la visita.</string> - <string name="err_log_load_data_again">Lo siento, c:geo no puede cargar los datos necesarios para registrar la visita. Intentándolo de nuevo.</string> - <string name="err_log_load_data_still">c:geo sigue cargando datos para registrar el escondite. Debes esperar un poquito mas.</string> - <string name="err_log_post_failed">Lo siento, c:geo no ha podido enviar el registro.</string> - <string name="err_log_post_failed_ec">Parece ser que su registro no ha sido publicado. Por favor compruébelo en Extremcaching.com.</string> - <string name="err_logimage_post_failed">Parece que su imagen de registro no se ha enviado al servidor. Compruébelo en Geocaching.com.</string> - <string name="err_search_address_forgot">Lo siento, c:geo ha olvidado la dirección que buscabas.</string> - <string name="err_parse_lat">Lo siento, c:geo no puede procesar la latitud.</string> - <string name="err_parse_lon">Lo siento, c:geo no puede procesar la longitud.</string> - <string name="err_parse_dist">Lo siento, c:geo can\'t no puede procesar la distancia.</string> + <string name="err_log_load_data">c:geo no puede cargar los datos necesarios para registrar la visita.</string> + <string name="err_log_load_data_again">c:geo no puede cargar los datos necesarios para registrar la visita. Intentándolo de nuevo.</string> + <string name="err_log_load_data_still">c:geo sigue cargando datos para registrar el caché. Debes esperar un poquito más.</string> + <string name="err_log_post_missing_tracking_code">Falta el código rastreable.</string> + <string name="err_log_post_missing_coordinates">Faltan las coordenadas.</string> + <string name="err_log_post_failed">Parece que tu registro no ha sido publicado. Compruébalo en la página original del caché.</string> + <string name="err_log_post_failed_ec">Parece que su registro no ha sido publicado. Por favor compruébalo en Extremcaching.com.</string> + <string name="err_log_post_failed_gk">Parece que su registro no ha sido publicado. Por favor compruébalo en geokrety.org.</string> + <string name="err_logimage_post_failed">Parece que tu imagen no se ha subido. Compruébalo en la página original del caché.</string> + <string name="err_search_address_forgot">c:geo ha olvidado la dirección que buscabas.</string> + <string name="err_parse_lat">c:geo no puede procesar la latitud.</string> + <string name="err_parse_lon">c:geo no puede procesar la longitud.</string> + <string name="err_parse_dist">c:geo no puede procesar la distancia.</string> <string name="err_parse_lat_lon">c:geo no ha podido interpretar la latitud o la longitud.</string> <string name="warn_save_nothing">No hay nada para guardar.</string> - <string name="warn_no_cache_coord">No hay escondite con coordenadas.</string> + <string name="warn_no_cache_coord">No hay cachés con coordenadas.</string> <string name="warn_no_coordinates">No se han dado coordenadas.</string> <string name="warn_no_keyword">No se ha indicado ninguna palabra clave.</string> <string name="warn_no_username">No se ha indicado nombre de usuario.</string> <string name="warn_search_help_title">¿Necesitas ayuda?</string> <string name="warn_search_help_address">\"Rellena la dirección o el nombre del lugar. Por ejemplo usa la dirección \"Gran VÃa 100, Vigo, España\", nombre de la ciudad \"Pontevedra\" o nombra a algo como \"Lagunas de Ruidera\".</string> - <string name="warn_search_help_gccode">Indica el código del escondite. Por ejemplo \"GC1VCAZ\".</string> - <string name="warn_search_help_keyword">Escribe algo que se suponga que está contenido en el nombre del escondite que buscas.</string> + <string name="warn_search_help_gccode">Indica el código del caché. Por ejemplo \"GC1VCAZ\".</string> + <string name="warn_search_help_keyword">Escribe todo o parte del nombre del caché. Por ejemplo \"Caché nocturno\".</string> <string name="warn_search_help_user">Escribe el nombre de usuario de Geocaching.com.</string> <string name="warn_search_help_tb">Escribe el código del rastreable. Por ejemplo \"TB29QMZ\".</string> <string name="warn_log_text_fill">Escribe algún texto de registro.</string> @@ -199,8 +209,8 @@ <string name="warn_rendertheme_missing">No se ha encontrado el esquema de colores del mapa.</string> <string name="warn_pocket_query_select">No ha seleccionado ninguna Pocket Query.</string> <string name="warn_no_pocket_query_found">No se ha encontrado ninguna Pocket Query en Geocaching.com.</string> - <string name="info_log_posted">c:geo registro enviado sin problemas.</string> - <string name="info_log_saved">c:geo guardado sin problemas.</string> + <string name="info_log_posted">c:geo envió el registro sin problemas.</string> + <string name="info_log_saved">c:geo guardó el registro sin problemas.</string> <string name="info_log_cleared">Registro borrado.</string> <string name="info_log_type_changed">¡El tipo de registro ha sido cambiado!</string> <string name="info_select_logimage_cancelled">La selección de imagen o captura ha sido cancelada.</string> @@ -211,6 +221,7 @@ <string name="loc_net">Red</string> <string name="loc_fused">Combinado</string> <string name="loc_low_power">Ahorro de energÃa</string> + <string name="loc_home">Coordenadas de casa</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Intentando ubicar</string> @@ -220,58 +231,65 @@ <string name="menu_about">Sobre c:geo</string> <string name="menu_helpers">Programas útiles</string> <string name="menu_settings">Ajustes</string> - <string name="menu_history">Historia</string> + <string name="menu_history">Historial</string> <string name="menu_filter">Filtro</string> <string name="menu_scan_geo">Escánear geocódigo</string> - <string name="menu_pocket_queries">Pocket queries</string> + <string name="menu_pocket_queries">Pocket Queries</string> <string name="menu_scan_description">c:geo puede escanear geocódigos que están impresos como código QR. La aplicación necesaria no está instalada. ¿Quiere abrir Google Play para instalarlo?</string> <string name="live_map_button">Mapa</string> <string name="caches_nearby_button">Cercanos</string> <string name="advanced_search_button">Buscar</string> <string name="stored_caches_button">Guardados</string> - <string name="any_button">Manual</string> + <string name="any_button">Ir a</string> <string name="unknown_scan">No se ha encontrado ningún geocódigo en la imagen.</string> - <string name="caches_no_cache">Ningún escondite</string> - <string name="caches_more_caches">Buscar mas</string> - <string name="caches_more_caches_no">No hay mas escondites</string> - <string name="caches_more_caches_loading">Cargando escondites…</string> + <string name="caches_no_cache">Ningún caché</string> + <string name="caches_more_caches">Cargar más cachés</string> + <string name="caches_more_caches_no">No hay más cachés</string> + <string name="caches_more_caches_loading">Cargando cachés…</string> <string name="caches_more_caches_currently">actualmente</string> - <string name="caches_downloading">Descargando escondites…\nFaltan: </string> + <string name="caches_downloading">Descargando cachés…\nFaltan: </string> <string name="caches_eta_ltm">Menos de un minuto</string> <plurals name="caches_eta_mins"> <item quantity="one">%d minuto</item> <item quantity="other">%d minutos</item> </plurals> <string name="caches_store_offline">Usar sin conexión luego</string> - <string name="caches_store_selected">Almacenamiento seleccionado</string> + <string name="caches_store_selected">Guardar seleccionados</string> <string name="caches_history">Historial</string> <string name="caches_on_map">Ver en mapa</string> <string name="caches_sort">Ordenar</string> - <string name="caches_sort_distance">distancia</string> - <string name="caches_sort_difficulty">dificultad</string> - <string name="caches_sort_terrain">terreno</string> - <string name="caches_sort_size">tamaño</string> + <string name="caches_sort_distance">Distancia</string> + <string name="caches_sort_difficulty">Dificultad</string> + <string name="caches_sort_terrain">Terreno</string> + <string name="caches_sort_size">Tamaño</string> <string name="caches_sort_favorites">Favoritos</string> <string name="caches_sort_favorites_ratio">Favoritos [%]</string> - <string name="caches_sort_name">nombre</string> - <string name="caches_sort_geocode">Código</string> - <string name="caches_sort_rating">valoración</string> - <string name="caches_sort_vote">votar (valoración propia)</string> - <string name="caches_sort_inventory">recuento de inventario</string> - <string name="caches_sort_date_hidden">fecha</string> + <string name="caches_sort_name">Nombre</string> + <string name="caches_sort_geocode">Código GC</string> + <string name="caches_sort_rating">Valoración</string> + <string name="caches_sort_vote">Votos (valoración propia)</string> + <string name="caches_sort_inventory">Recuento de inventario</string> + <string name="caches_sort_date_hidden">Fecha escondido</string> <string name="caches_sort_date_logged">Fecha de registro</string> <string name="caches_sort_finds">Encontrados</string> <string name="caches_sort_state">Estado</string> - <string name="caches_sort_storage">Fecha almacenada en el dispositivo</string> + <string name="caches_sort_storage">Fecha de guardado en dispositivo</string> + <string name="caches_sort_eventdate">Fecha del evento</string> <string name="caches_select_mode">Modo selección</string> <string name="caches_select_mode_exit">Salir de modo selección</string> <string name="caches_select_invert">Invertir selección</string> <string name="caches_nearby">Cercanos</string> <string name="caches_manage">Gestionar</string> <string name="caches_remove_all">Eliminar todos</string> - <string name="caches_remove_all_confirm">¿Desea eliminar todos los cachés (%s) de la lista actual?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">¿Quieres eliminar este caché de la lista actual?</item> + <item quantity="other">¿Quieres eliminar los %d cachés de la lista actual?</item> + </plurals> <string name="caches_remove_selected">Eliminar los seleccionados</string> - <string name="caches_remove_selected_confirm">¿Desea eliminar los %s cachés seleccionados de su dispositivo?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">¿Quieres eliminar este caché del dispositivo?</item> + <item quantity="other">¿Quieres eliminar los %d cachés seleccionados del dispositivo?</item> + </plurals> <string name="caches_remove_progress">Eliminando los cachés</string> <string name="caches_delete_events">Borrar eventos pasados</string> <string name="caches_refresh_selected">Actualizar seleccionados</string> @@ -281,37 +299,42 @@ <string name="caches_map_locus">Locus</string> <string name="caches_map_locus_export">Exportar a Locus</string> <string name="caches_recaptcha_title">reCAPTCHA</string> - <string name="caches_recaptcha_explanation">Debes escribir el texto de la imagen. Es importante que descargues las coordenadas de los escondites. Es opcional y lo puedes desactivar en Ajustes.</string> + <string name="caches_recaptcha_explanation">Por favor escribe el texto de la imagen. Esto permite descargar las coordenadas de los cachés. Es opcional y lo puedes desactivar en Ajustes.</string> <string name="caches_recaptcha_hint">Texto de la imagen</string> <string name="caches_recaptcha_continue">Continuar</string> <string name="caches_filter">Filtrar</string> <string name="caches_filter_title">Filtrar por</string> - <string name="caches_filter_size">tamaño</string> - <string name="caches_filter_type">tipo</string> - <string name="caches_filter_track">con rastreables</string> - <string name="caches_filter_clear">limpiar filtros</string> + <string name="caches_filter_size">Tamaño</string> + <string name="caches_filter_type">Tipo</string> + <string name="caches_filter_track">Con rastreables</string> + <string name="caches_filter_clear">Limpiar filtros</string> <string name="caches_filter_modified">Con las coordenadas modificadas</string> + <string name="caches_filter_offline_log">Con registro sin conexión</string> <string name="caches_filter_origin">Coordenadas originales</string> <string name="caches_filter_distance">Distancia</string> <string name="caches_filter_personal_note">Con nota personal</string> <string name="caches_filter_popularity">Favoritos</string> <string name="caches_filter_popularity_ratio">Favoritos [%]</string> + <string name="caches_filter_personal_data">Con datos personales</string> + <string name="caches_filter_rating">Con puntuación</string> + <string name="caches_filter_own_rating">Con puntuación propia</string> <string name="caches_removing_from_history">Borrando del historial…</string> <string name="caches_clear_offlinelogs">Borrar registros sin conexión</string> + <string name="caches_clear_offlinelogs_message">¿Quieres borrar los registros sin conexión?</string> <string name="caches_clear_offlinelogs_progress">Borrando registros sin conexión</string> <string name="list_menu_create">Crear nueva lista</string> <string name="list_menu_drop">Borrar lista actual</string> <string name="list_menu_rename">Renombrar la lista actual</string> <string name="list_menu_import">Importar</string> <string name="list_title">Escoger lista</string> - <string name="list_inbox">Guardadas</string> - <string name="list_all_lists">Todos los caches</string> + <string name="list_inbox">Guardados</string> + <string name="list_all_lists">Todos los cachés</string> <string name="list_dialog_create_title">Nueva lista</string> <string name="list_dialog_create">Crear</string> <string name="list_dialog_create_ok">Se ha creado una nueva lista</string> <string name="list_dialog_create_err">c:geo no ha podido crear la lista</string> <string name="list_dialog_remove_title">Borrar lista</string> - <string name="list_dialog_remove_description">¿Quieres borrar esta lista de escondites? Todos los escondites de la lilsta serán movidos a \"Guardados\".</string> + <string name="list_dialog_remove_description">¿Quieres borrar la lista actual? Todos los cachés de la lista serán movidos a \"Guardados\".</string> <string name="list_dialog_remove">Borrar</string> <string name="list_dialog_remove_ok">La lista ha sido borrada</string> <string name="list_dialog_remove_err">c:geo no ha podido borrar la lista actual</string> @@ -320,17 +343,21 @@ <string name="list_not_available">La lista ya no está disponible, cambiando a la lista estándar</string> <string name="about_version">Versión</string> <string name="about_changelog">Cambios</string> + <string name="about_system">Sistema</string> <string name="about_donate">Donar</string> - <string name="about_donation_more">Donar\nmas</string> + <string name="about_donation_more">Donar para el\ndesarrollo de c:geo</string> <string name="about_contributors">Colaboradores</string> <string name="about_license">Licencia</string> <string name="about_apache_license"><a href="">Licencia Apache, Versión 2.0</a></string> <string name="about_help">Ayuda</string> + <string name="about_system_include">Por favor, incluya la siguiente información del sistema cuando envÃe un informe de error o pida más información sobre c:geo:</string> + <string name="changelog_github">Lista de todos los cambios</string> <string name="settings_title_services">Servicios</string> + <string name="settings_summary_services">Configura la información de la cuenta de usuario y accede a servicios opcionales.</string> <string name="settings_title_appearance">Aspecto</string> - <string name="settings_title_cachedetails">Detalles del cache</string> + <string name="settings_title_cachedetails">Detalles del caché</string> <string name="settings_title_offlinedata">Datos sin conexión</string> - <string name="settings_title_logging">Registrar</string> + <string name="settings_title_logging">Registro</string> <string name="settings_title_map">Mapa</string> <string name="settings_title_map_data">Datos del mapa</string> <string name="settings_title_map_content">Contenido del mapa</string> @@ -348,24 +375,27 @@ <string name="settings_activate_ec">Activar</string> <string name="settings_activate_ox">Activar</string> <string name="settings_gc_legal_note">Usando el servicio de geocaching.com, usted acepta los términos de uso de Groundspeak.</string> - <string name="settings_info_facebook_login_title">Facebook Login</string> + <string name="settings_info_facebook_login_title">Conectarse con Facebook</string> <string name="settings_info_facebook_login">No puedes iniciar sesión en geocaching.com desde c:geo con tu cuenta de Facebook. Pero esto se puede solucionar con un simple truco…</string> <string name="settings_authorize">Autorizar c:geo</string> <string name="settings_reauthorize">Autorizar c:geo otra vez</string> <string name="init_oc">Opencaching.de</string> <string name="settings_activate_oc">Activar</string> - <string name="init_oc_de_description">Autorizar que c:geo pueda usar opencaching.de para buscar caches y acceder a / filtrar tus caches encontrados.</string> + <string name="init_oc_de_description">Autorizar que c:geo pueda usar opencaching.de para buscar cachés y acceder a / filtrar tus cachés encontrados.</string> <string name="settings_activate_oc_pl">Activar</string> - <string name="init_oc_pl_description">Autorizar que c:geo pueda usar opencaching.pl para buscar caches y acceder a / filtrar tus caches encontrados.</string> + <string name="init_oc_pl_description">Autorizar que c:geo pueda usar opencaching.pl para buscar cachés y acceder a / filtrar tus cachés encontrados.</string> <string name="settings_activate_oc_nl">Activar</string> - <string name="init_oc_nl_description">Autorizar que c:geo pueda usar opencaching.nl para buscar caches y acceder a / filtrar tus caches encontrados.</string> + <string name="init_oc_nl_description">Autorizar que c:geo pueda usar opencaching.nl para buscar cachés y acceder a / filtrar tus cachés encontrados.</string> <string name="settings_activate_oc_us">Activar</string> - <string name="init_oc_us_description">Autorizar que c:geo pueda usar opencaching.us para buscar caches y acceder a / filtrar tus caches encontrados.</string> + <string name="init_oc_us_description">Autorizar que c:geo pueda usar opencaching.us para buscar cachés y acceder a / filtrar tus cachés encontrados.</string> <string name="settings_activate_oc_ro">Activar</string> - <string name="init_oc_ro_description">Autorizar que c:geo pueda usar opencaching.ro para buscar caches y acceder a / filtrar tus caches encontrados.</string> + <string name="init_oc_ro_description">Autorizar que c:geo pueda usar opencaching.ro para buscar cachés y acceder a / filtrar tus cachés encontrados.</string> <string name="settings_activate_oc_uk">Activar</string> - <string name="init_oc_uk_description">Autorizar que c:geo pueda usar opencaching.org.uk para buscar caches y acceder a / filtrar tus cachés encontrados.</string> + <string name="init_oc_uk_description">Autorizar que c:geo pueda usar opencaching.org.uk para buscar cachés y acceder a / filtrar tus cachés encontrados.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Para poder calificar un caché, tienes que seguir las instrucciones en GCVote.com e introducir tu contraseña de GCVote aquÃ.</string> + <string name="err_gcvote_send_rating">Error al enviar la calificación, comprueba tu contraseña de GCVote en configuración o déjala en blanco.</string> + <string name="gcvote_sent">Voto enviado con éxito</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activar</string> <string name="init_username">Usuario</string> @@ -392,71 +422,73 @@ <string name="init_signature_template_name">Nombre</string> <string name="init_signature_template_url">URL</string> <string name="init_signature_template_log">Texto de registro</string> - <string name="init_ratingwanted">Clasificación de GCvote</string> + <string name="init_ratingwanted">Puntuación de GCvote</string> <string name="init_summary_ratingwanted">Cargar la puntuación del cache desde GCvote.com</string> - <string name="init_friends_and_own_logs_wanted">Mostrar logs de amigos / propios</string> - <string name="init_summary_friends_and_own_logs_wanted">Mostrar una página adicional para los logs de amigos y propios</string> - <string name="init_openlastdetailspage">Detalles de la última página</string> - <string name="init_summary_openlastdetailspage">Recordar última vista usada al consultar los detalles del cache</string> - <string name="init_autoload">Autocargar descripción larga</string> + <string name="init_friends_and_own_logs_wanted">Mostrar amigos / propios</string> + <string name="init_summary_friends_and_own_logs_wanted">Mostrar una página adicional para los registros de amigos y propios</string> + <string name="init_openlastdetailspage">Recordar última página</string> + <string name="init_summary_openlastdetailspage">Mostrar última página vista al consultar los detalles del caché</string> + <string name="init_autoload">Descripción larga</string> <string name="init_summary_autoload">Autocargar descripción larga</string> - <string name="init_skin">Fondo blanco (necesita reiniciar c:geo)</string> - <string name="init_summary_skin">Fondo blanco (necesita reiniciar c:geo)</string> - <string name="init_address">Mostrar dirección en lugar de posición en la pantalla principal</string> - <string name="init_summary_address">Mostrar dirección en lugar de posición en la pantalla principal</string> - <string name="init_captcha">Mostrar CAPTCHA si es necesario</string> - <string name="init_summary_captcha">Mostrar CAPTCHA si es necesario</string> - <string name="init_useenglish">Usar inglés interno (necesita reiniciar c:geo)</string> - <string name="init_summary_useenglish">Usar inglés interno (necesita reiniciar c:geo)</string> + <string name="init_skin">Fondo blanco</string> + <string name="init_summary_skin">Usar fondo blanco (necesitas reiniciar c:geo)</string> + <string name="init_address">Mostrar dirección</string> + <string name="init_summary_address">Mostrar dirección en lugar de coordenadas en la pantalla principal</string> + <string name="init_captcha">Mostrar CAPTCHA</string> + <string name="init_summary_captcha">Mostrar CAPTCHA si es necesario (sólo miembros básicos)</string> + <string name="init_useenglish">Usar inglés</string> + <string name="init_summary_useenglish">Usar c:geo en inglés (se necesita reiniciar)</string> <string name="init_exclude">Excluir encontrados y propios</string> - <string name="init_summary_exclude">Excluir encontrados y propios</string> + <string name="init_summary_exclude">Excluir cachés ya encontrados y propios</string> <string name="init_showwaypoints">Mostrar Waypoints</string> - <string name="init_showwaypoint_description">Mostar los puntos de referencia de los caches mostrados si en el mapa se hay menos caches que la cantidad indicada.</string> - <string name="init_disabled">Excluir escondites desactivados</string> - <string name="init_summary_disabled">Excluir escondites desactivados</string> - <string name="init_offline">Guardar mapas para usar sin conexión</string> - <string name="init_summary_offline">Guardar mapas para usar sin conexión</string> + <string name="init_showwaypoint_description">Mostrar los waypoints de los cachés si en el mapa se muestran menos cachés que el número seleccionado.</string> + <string name="init_disabled">Excluir desactivados</string> + <string name="init_summary_disabled">Excluir cachés desactivados</string> + <string name="init_offline">Mapas estáticos</string> + <string name="init_summary_offline">Guardar mapas estáticos de los cachés para usar sin conexión</string> <string name="init_offline_wp">Mapas estáticos (WP)</string> <string name="init_summary_offline_wp">Guardar waypoints en los mapas estáticos para su uso sin conexión</string> - <string name="init_save_log_img">Guardar imágenes de los registros</string> + <string name="init_save_log_img">Guardar imágenes</string> <string name="init_summary_save_log_img">Guardar imágenes de los registros</string> - <string name="init_units">Usar millas/pies (unidades imperiales)</string> + <string name="init_units">Usar millas/pies</string> <string name="init_summary_units">Usar millas/pies (unidades imperiales)</string> - <string name="init_log_offline">Log sin conexión</string> + <string name="init_log_offline">Registro sin conexión</string> <string name="init_summary_log_offline">Permitir el registro sin conexión (No se mostrará la pantalla de registro en lÃnea ni se enviarán los logs)</string> - <string name="init_choose_list">Pida lista</string> - <string name="init_summary_choose_list">Pregunte qué lista para almacenar en caché</string> - <string name="init_livelist">Mostrar dirección a los escondites en su listado</string> - <string name="init_summary_livelist">Mostrar dirección a los escondites en su listado</string> - <string name="init_backup">Backup</string> + <string name="init_choose_list">Preguntar lista</string> + <string name="init_summary_choose_list">Preguntar en qué lista guardar el caché</string> + <string name="init_livelist">Mostrar dirección</string> + <string name="init_summary_livelist">Mostrar la dirección de los cachés en la lista</string> + <string name="init_backup">Copia de seguridad</string> <string name="init_backup_backup">Copia de seguridad</string> <string name="init_backup_running">Creando copia de seguridad de la base de datos de cachés…</string> - <string name="init_backup_note">Esta opción copia/restaura la base de datos de escondites y puntos de referencia, no la configuración. Los datos de acceso y contraseña no se guardarán.</string> + <string name="init_backup_note">Esta opción copia/restaura la base de datos de cachés y puntos de referencia, no la configuración.\nTus datos de acceso y contraseña no se guardarán.</string> <string name="init_backup_restore">Restaurar</string> - <string name="init_backup_success">La base de datos de c:geo se ha copiado satisfactoriamente</string> + <string name="init_backup_success">La base de datos de c:geo se ha copiado a:</string> <string name="init_backup_failed">Ha fallado la copia de seguridad.</string> <string name="init_backup_unnecessary">La base de datos está vacÃa, no es necesaria una copia de seguridad.</string> + <string name="backup_confirm_overwrite">¿Quieres sobreescribir la copia de seguridad existente de %s?</string> + <string name="restore_confirm_overwrite">¿Quieres sobreescribir %s en tu dispositivo con la copia de seguridad?</string> <string name="init_restore_success">Restauración completa.</string> - <string name="init_restore_failed">Restauración errónea</string> + <string name="init_restore_failed">Restauración errónea.</string> <string name="init_restore_running">Restaurando la base de datos de cachés…</string> <string name="init_restore_confirm">La base de datos está vacia. ¿Desea restaurar la copia de seguridad de la base de datos?</string> <string name="init_backup_last">Copia guardada el</string> <string name="init_backup_last_no">No hay ninguna copia de seguridad.</string> - <string name="settings_info_offline_maps_title">Información sobre mapas sin conexión</string> - <string name="settings_info_offline_maps">c:geo permite mapas de uso sin conexión. Puedes descargar mapas desde Mapsforge o incluso crear los tuyos propios desde los datos de OSM (Open Street Map). Necesitas seleccionar primero el directorio de mapas sin conexión para obtener soporte para mapas sin conexión.</string> + <string name="settings_info_offline_maps_title">Mapas sin conexión</string> + <string name="settings_info_offline_maps">c:geo permite el uso de mapas sin conexión. Puedes descargar mapas desde Mapsforge o incluso crear los tuyos propios desde los datos de OSM (Open Street Map). Necesitas seleccionar primero el directorio con los mapas sin conexión para poder usarlos.</string> <string name="settings_info_themes_title">Información sobre temas de mapas</string> <string name="settings_info_themes">c:geo permite personalizar los mapas sin conexión. Se puede usar para cambiar el estilo del color del mapa (p. ej. tener un mapa de visión nocturna) o para resatar ciertos objetos como carriles bici o lÃneas de altitud en el mapa.</string> - <string name="init_mapsource_select">Elige proveedor de mapas</string> + <string name="init_mapsource_select">Elegir proveedor de mapas</string> <string name="settings_title_scale_map_text">Escalar el texto del mapa</string> <string name="settings_summary_scale_map_text">Escala el texto de los mapas sin conexión según los p.p.p. del dispositivo</string> <string name="init_map_directory_description">Directorio de mapas sin conexión</string> - <string name="init_gpx_exportdir">Directorio de exportación de GPX</string> - <string name="init_gpx_importdir">Directorio de importación de GPX</string> - <string name="init_maptrail">Mostrar rastro en el mapa</string> + <string name="init_gpx_exportdir">Directorio para exportar GPX</string> + <string name="init_gpx_importdir">Directorio para importar GPX</string> + <string name="init_maptrail">Mostrar rastro</string> <string name="init_summary_maptrail">Muestra el rastro en el mapa</string> <string name="init_share_after_export">Abrir el menú de compartir tras exportar GPX</string> - <string name="init_trackautovisit">Convertir rastreables automáticamente a \"visita\"</string> - <string name="init_summary_trackautovisit">Convertir rastreables automáticamente a \"visita\"</string> + <string name="init_trackautovisit">Convertir TBs a Visitado</string> + <string name="init_summary_trackautovisit">Convertir rastreables automáticamente a \"Visitado\"</string> <string name="init_sigautoinsert">Insertar automáticamente</string> <string name="init_loaddirectionimg">Imagen de dirección</string> <string name="init_summary_loaddirectionimg">Descarga si es necesario las imágenes de las flechas direccionales (necesario solo para miembros básicos)</string> @@ -476,11 +508,11 @@ <string name="init_dbmove_running">Moviendo base de datos</string> <string name="init_dbmove_success">Base de datos movida con éxito.</string> <string name="init_dbmove_failed">Error al mover la base de datos</string> - <string name="init_plain_logs">Logs sencillos</string> - <string name="init_summary_plain_logs">Muestra los logs sin usar colores</string> + <string name="init_plain_logs">Registros sencillos</string> + <string name="init_summary_plain_logs">Muestra los registros sin usar colores</string> <string name="init_use_native_ua">Navegador de Android</string> <string name="init_summary_use_native_ua">Identificarse como usuario Android. Resuelve algunos problemas de acceso cuando se usan ciertos proveedores de red.</string> - <string name="init_rendertheme_folder">Mapa directorio de temas</string> + <string name="init_rendertheme_folder">Directorio de temas para mapas</string> <string name="init_maintenance">Mantenimiento</string> <string name="init_maintenance_directories_note">c:Geo almacena imágenes, registro de imágenes y otros archivos relacionados con una memoria caché en un directorio separado. En algunos casos (como importar/exportar la base de datos) este directorio puede contener archivos obsoletos, que aquà se pueden eliminar.</string> <string name="init_maintenance_directories">Eliminar archivos huérfanos</string> @@ -489,7 +521,7 @@ <string name="init_location_googleplayservices">Usar servicios de Google Play</string> <string name="init_low_power">Modo ahorro energÃa</string> <string name="init_low_power_note">El modo de ahorro de energÃa evita el uso del GPS y del giroscopio cuando no es necesaria una ubicación muy precisa, a costa de aumentar el tiempo para fijar los satélites.</string> - <string name="init_low_power_mode">Activar modo ahorro de energÃa</string> + <string name="init_low_power_mode">Activar ahorro de energÃa</string> <string name="init_create_memory_dump">Crear volcado de memoria</string> <string name="init_memory_dump">Volcado de memoria</string> <string name="init_memory_dumped">Memoria volcada a %s</string> @@ -497,6 +529,7 @@ <string name="init_hardware_acceleration_note">La aceleración por hardware renderiza los elementos gráficos en pantalla de manera más rápida. Sin embargo en algunos dispositivos el sistema operativo Android contiene fallos y algunos textos pueden aparecer borrosos (especialmente caracteres en negrita). Inhabilita la aceleración por hardware si ocurriera esto.</string> <string name="init_hardware_acceleration">Habilitar aceleración por hardware</string> <string name="settings_open_website">Abrir el sitio web</string> + <string name="settings_open_geokretymap_website">Abrir el sitio web GeokretyMap.org</string> <string name="settings_settings">Ajustes</string> <string name="settings_information">Información</string> <string name="settings_twitter_cache_message">Mensaje para caché encontrado</string> @@ -510,7 +543,7 @@ <string name="feature_online_logging">Registro online</string> <string name="feature_log_images">Adjuntar imágenes a los registros</string> <string name="feature_watch_list">Lista de seguimiento</string> - <string name="feature_own_coordinates">Almacenamiento de coordenadas modificadas</string> + <string name="feature_own_coordinates">Almacenar coordenadas modificadas</string> <string name="feature_search_keyword">Buscar por palabra clave</string> <string name="feature_search_live_map">Mapa en vivo</string> <string name="feature_search_center">Búsqueda por posición</string> @@ -523,28 +556,28 @@ <string name="map_source_osm_cyclemap">OSM: Cyclemap</string> <string name="map_source_osm_offline">Offline</string> <string name="init_sendToCgeo">Enviar a c:geo</string> - <string name="settings_info_send2cgeo_title">Info de send2cgeo</string> + <string name="settings_info_send2cgeo_title">Sobre Enviar a c:geo</string> <string name="init_sendToCgeo_name">Nombre de tu dispositivo</string> - <string name="init_sendToCgeo_description">Enviar a c:geo (send2cgeo)te permite recibir escondites automáticamente desde la web de geocaching usando un complemento especialpara Firefox o Chrome. Antes de registrarte, te sugerimos que leas <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Sólo necesitas registarte si vas a usar send2cgeo. C:geo funciona sin tener que registrar tu dispositivo.</string> + <string name="init_sendToCgeo_description"><b>Send2c:geo</b> te permite recibir cachés automáticamente desde la web de geocaching usando un complemento especial para Firefox o Chrome. Antes de registrarte, te sugerimos que leas <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Sólo necesitas registarte si vas a usar send2cgeo. c:geo funciona sin tener que registrar tu dispositivo.</string> <string name="init_sendToCgeo_register">Solicitar registro</string> <string name="init_sendToCgeo_registering">Registrando \"Enviar a c:geo\"…</string> <string name="init_sendToCgeo_register_ok">Registro finalizado. Tu código PIN ####. Úsalo en la web de c:geo para añadir este dispositivo a tu navegador.</string> <string name="init_sendToCgeo_register_fail">Error al registrarse.</string> <string name="sendToCgeo_download_fail">c:geo no ha podido descargar cachés. No hay conexión a internet o send2c:geo no está disponible.</string> - <string name="sendToCgeo_no_registration">c:geo no ha podido descargar cachés. El registro en send2c:geo ha expirado. Por favor registrate en configuración.</string> + <string name="sendToCgeo_no_registration">c:geo no ha podido descargar cachés. El registro en send2c:geo ha expirado. Por favor registrate en ajustes.</string> <string name="auth_twitter">Twitter</string> <string name="auth_authorize">Autorizar c:geo</string> <string name="auth_start">Iniciar autorización</string> <string name="auth_again">Volver a iniciar</string> <string name="auth_dialog_waiting">Esperando a %s…</string> - <string name="auth_explain_short">El suiguiente proceso permitirá a <b>c:geo</b> acceder a %s.</string> - <string name="auth_explain_long">Presionando el botón \"Autoriza a c:geo\" comenzará el proceso. Este proceso abrirá el navegador web con una página %s. Resgistrate en esta página y permite a <b>c:geo</b> acceder a tu cuenta. Eso es todo.</string> + <string name="auth_explain_short">El siguiente proceso permitirá a <b>c:geo</b> acceder a %s.</string> + <string name="auth_explain_long">Presionando el botón \"Autorizar c:geo\" comenzará el proceso. Este proceso abrirá el navegador web con una página %s. Registrate en esta página y permite a <b>c:geo</b> acceder a tu cuenta. Eso es todo.</string> <string name="auth_dialog_completed_twitter">c:geo está autorizado ahora a publicar en Twitter.</string> <string name="auth_ocde">Opencaching.de</string> <string name="auth_dialog_completed_oc">c:geo está autorizado a interactuar con %s.</string> <plurals name="cache_counts"> - <item quantity="one">Un escondite</item> - <item quantity="other">%1$d Escondites</item> + <item quantity="one">Un caché</item> + <item quantity="other">%1$d cachés</item> </plurals> <string name="cache_offline">Desconectado</string> <string name="cache_offline_refresh">Actualizar</string> @@ -552,7 +585,7 @@ <string name="cache_offline_store">Guardar</string> <string name="cache_offline_stored">Guardado en el dispositivo</string> <string name="cache_offline_not_ready">No preparado\npara usar desconectado</string> - <string name="cache_offline_time_about">Acerca</string> + <string name="cache_offline_time_about">desde</string> <string name="cache_offline_time_mins">minutos atrás</string> <string name="cache_offline_time_mins_few">hace unos minutos</string> <string name="cache_offline_time_hour">hace una hora</string> @@ -561,21 +594,21 @@ <string name="cache_premium">Premium</string> <string name="cache_attributes">Atributos</string> <string name="cache_inventory">Inventario</string> - <string name="cache_log_images_title">Imagen de registro</string> + <string name="cache_log_images_title">Imágenes de registros</string> <string name="cache_log_image_default_title">Foto</string> <string name="cache_personal_note">Nota personal</string> <string name="cache_personal_note_edit">Editar</string> <string name="cache_personal_note_limit">LÃmite de la nota personal</string> <string name="cache_personal_note_truncation">Geocaching.com cortará esta nota personal después de %d caracteres.</string> <string name="cache_personal_note_upload">Subir</string> - <string name="cache_personal_note_uploading">Subir nota personal</string> + <string name="cache_personal_note_uploading">Cargando nota personal</string> <string name="cache_personal_note_upload_done">Nota personal cargada</string> - <string name="cache_personal_note_upload_cancelled">Subir nota personal cancelado</string> + <string name="cache_personal_note_upload_cancelled">Se ha cancelado la carga de la nota personal</string> <string name="cache_description">Descripción</string> <string name="cache_description_long">Descripción larga</string> <string name="cache_description_table_note">La descripción contiene formato de tabla que puede necesitar ser vista en %s para mostrarse correctamente.</string> - <string name="cache_watchlist_on">Este escondite está en tu Lista de seguimiento.</string> - <string name="cache_watchlist_not_on">Este escondite no está en tu Lista de seguimiento.</string> + <string name="cache_watchlist_on">Este caché está en tu Lista de seguimiento.</string> + <string name="cache_watchlist_not_on">Este caché no está en tu Lista de seguimiento.</string> <string name="cache_watchlist_add">Añadir a Lista de seguimiento</string> <string name="cache_watchlist_remove">Borrar de la Lista de seguimiento</string> <string name="cache_favpoint_on">Este caché es uno de tus favoritos.</string> @@ -586,42 +619,43 @@ <string name="cache_list_change">Mover</string> <string name="cache_list_unknown">No está en lista</string> <string name="cache_images">Imágenes</string> - <string name="cache_waypoints">Puntos de referencia</string> + <string name="cache_waypoints">Waypoints</string> <plurals name="waypoints"> <item quantity="one">1 Waypoint</item> <item quantity="other">%d Waypoints</item> </plurals> - <string name="cache_waypoints_add">Añadir referencia</string> + <string name="cache_waypoints_add">Añadir waypoint</string> <string name="cache_hint">Pista</string> - <string name="cache_logs">Bitácora</string> + <string name="cache_hint_not_available">No hay pista disponible</string> + <string name="cache_logs">Registros</string> <string name="cache_logs_friends_and_own">Amigos/propios</string> - <string name="cache_dialog_loading_details">Cargando detalles del escondite…</string> - <string name="cache_dialog_loading_details_status_loadpage">Cargando la página</string> + <string name="cache_dialog_loading_details">Cargando detalles del caché…</string> + <string name="cache_dialog_loading_details_status_loadpage">Cargando página</string> <string name="cache_dialog_loading_details_status_details">Procesando detalles</string> <string name="cache_dialog_loading_details_status_spoilers">Cargando imágenes spoiler</string> <string name="cache_dialog_loading_details_status_logs">Cargando registros</string> - <string name="cache_dialog_loading_details_status_waypoints">Procesando Waypoints</string> + <string name="cache_dialog_loading_details_status_waypoints">Procesando waypoints</string> <string name="cache_dialog_loading_details_status_gcvote">Cargando GCVote</string> - <string name="cache_dialog_loading_details_status_cache">Salvando datos</string> + <string name="cache_dialog_loading_details_status_cache">Almacenando datos</string> <string name="cache_dialog_loading_details_status_render">Procesando la representación</string> <string name="cache_dialog_offline_save_title">Desconectado</string> - <string name="cache_dialog_offline_save_message">Guardando escondite para usar desconectado…</string> + <string name="cache_dialog_offline_save_message">Guardando caché para usar desconectado…</string> <string name="cache_dialog_offline_drop_title">Desconectado</string> - <string name="cache_dialog_offline_drop_message">Borrando escondite de la memoria del dispositivo…</string> + <string name="cache_dialog_offline_drop_message">Borrando caché de la memoria del dispositivo…</string> <string name="cache_dialog_refresh_title">Actualizar</string> - <string name="cache_dialog_refresh_message">Recargando detalles del escondite…</string> + <string name="cache_dialog_refresh_message">Recargando detalles del caché…</string> <string name="cache_dialog_watchlist_add_title">Lista de seguimiento</string> - <string name="cache_dialog_watchlist_add_message">Añadiendo el escondite a tu Lista de seguimiento…</string> + <string name="cache_dialog_watchlist_add_message">Añadiendo el caché a tu Lista de seguimiento…</string> <string name="cache_dialog_watchlist_remove_title">Lista de seguimiento</string> - <string name="cache_dialog_watchlist_remove_message">Borrando escondite de tu Lista de seguimiento…</string> + <string name="cache_dialog_watchlist_remove_message">Borrando caché de tu Lista de seguimiento…</string> <string name="cache_dialog_favorite_add_title">Favorito</string> <string name="cache_dialog_favorite_add_message">Añadiendo el caché a tus favoritos…</string> <string name="cache_dialog_favorite_remove_title">Favorito</string> <string name="cache_dialog_favorite_remove_message">Borrando el caché de tus favoritos…</string> <string name="cache_menu_navigate">Navegar</string> - <string name="cache_menu_navigation_drive">Navegación (conduciendo)</string> - <string name="cache_menu_navigation_walk">Navegación (a pie)</string> - <string name="cache_menu_navigation_bike">Navegación (En bici)</string> + <string name="cache_menu_navigation_drive">Navegación (Coche)</string> + <string name="cache_menu_navigation_walk">Navegación (A Pie)</string> + <string name="cache_menu_navigation_bike">Navegación (Bici)</string> <string name="cache_menu_maps_directions">Direcciones de Google Maps</string> <string name="cache_menu_radar">Radar</string> <string name="cache_menu_map">Ver en mapa</string> @@ -630,23 +664,27 @@ <string name="cache_menu_rmaps">Rmaps</string> <string name="cache_menu_map_ext">Mostrar en mapa ext.</string> <string name="cache_menu_streetview">Street View</string> - <string name="cache_menu_browser">Navegador</string> - <string name="cache_menu_visit">Encontrado</string> - <string name="cache_menu_visit_offline">Registar vista sin conexión</string> + <string name="cache_menu_browser">Abrir navegador</string> + <string name="cache_menu_visit">Registrar visita</string> + <string name="cache_menu_visit_offline">Registro rápido sin conexión</string> <string name="cache_menu_spoilers">Revelaciones</string> - <string name="cache_menu_around">Alrededores</string> - <string name="cache_menu_event">Añadir a calendario</string> + <string name="cache_menu_around">Cachés cercanos</string> + <string name="around">Cerca de %s</string> + <string name="cache_menu_event">Añadir al calendario</string> <string name="cache_menu_details">Detalles</string> <string name="cache_menu_refresh">Actualizar</string> - <string name="cache_menu_share">Compartir escondite</string> + <string name="cache_menu_share">Compartir caché</string> <string name="cache_menu_move_list">Mover a otra lista</string> <string name="cache_menu_whereyougo">WhereYouGo</string> <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Votar</string> + <string name="cache_menu_checker">Abrir Geochecker</string> + <string name="cache_menu_ignore">Ignorar caché</string> <string name="cache_status">Estado</string> <string name="cache_status_offline_log">Registro guardado</string> <string name="cache_status_found">Encontrado</string> - <string name="cache_not_status_found">No encontrados</string> + <string name="cache_not_status_found">No encontrado</string> <string name="cache_status_archived">Archivado</string> <string name="cache_status_disabled">Desactivado</string> <string name="cache_status_premium">Sólo para miembros Premium</string> @@ -661,7 +699,7 @@ <string name="cache_difficulty">Dificultad</string> <string name="cache_terrain">Terreno</string> <string name="cache_rating">Puntuación</string> - <string name="cache_own_rating">Su calificación</string> + <string name="cache_own_rating">Tu puntuación</string> <string name="cache_rating_of">de</string> <string name="cache_favorite">Favorito</string> <string name="cache_owner">Propietario</string> @@ -672,7 +710,7 @@ <string name="cache_coordinates_original">Coordenadas originales</string> <string name="cache_spoiler_images_title">Imágenes reveladoras</string> <string name="cache_log_types">Tipos de registro</string> - <string name="cache_coordinates_no">Este escondite no tiene coordenadas.</string> + <string name="cache_coordinates_no">Este caché no tiene coordenadas.</string> <string name="cache_clear_history">Borrar historial</string> <string name="cache_remove_from_history">Borrar del historial</string> <string name="cache_license">Licencia</string> @@ -690,10 +728,10 @@ <string name="simple_dir_chooser_title">Elegir directorio</string> <string name="simple_dir_chooser_current_path">Ruta:</string> <string name="simple_dir_chooser_invalid_path">Ruta inválida</string> - <string name="gpx_import_loading_caches">Cargando escondites del archivo .gpx</string> + <string name="gpx_import_loading_caches">Cargando cachés del archivo .gpx</string> <string name="gpx_import_loading_waypoints">Cargando archivo de waypoints</string> - <string name="gpx_import_store_static_maps">Almacenar mapas estáticos</string> - <string name="gpx_import_caches_imported">escondites importados</string> + <string name="gpx_import_store_static_maps">Almacenando mapas estáticos</string> + <string name="gpx_import_caches_imported">cachés importados</string> <string name="gpx_import_static_maps_skipped">Descarga de mapas estáticos abortada</string> <string name="gpx_import_title_static_maps">Almacenar mapas estáticos</string> <string name="gpx_import_title_reading_file">Leyendo archivo</string> @@ -710,39 +748,40 @@ <string name="gpx_import_android">Importar desde Android</string> <string name="map_file_select_title">Selecciona un mapa</string> <string name="web_import_title">Importar de la web</string> - <string name="web_import_waiting">Esperando por nuevos escondites desde la web…</string> + <string name="web_import_waiting">Esperando a nuevos cachés desde la web…</string> <string name="web_downloading">Descargando</string> <string name="web_downloaded">Descargados</string> <string name="popup_more">Más detalles</string> <string name="waypoint">Waypoint</string> - <string name="waypoint_cache_coordinates">Coordenadas del cache</string> + <string name="waypoint_cache_coordinates">Coordenadas del caché</string> <string name="waypoint_custom">A medida</string> <string name="waypoint_my_coordinates">Mis coordenadas</string> - <string name="waypoint_bearing">Orientación</string> + <string name="waypoint_bearing">Orientación en º</string> <string name="waypoint_distance">Distancia</string> <string name="waypoint_name">Nombre</string> <string name="waypoint_edit">Editar</string> <string name="waypoint_delete">Borrar</string> - <string name="waypoint_edit_title">Editar punto de referencia</string> - <string name="waypoint_add_title">Añadir referencia</string> + <string name="waypoint_edit_title">Editar waypoint</string> + <string name="waypoint_add_title">Añadir waypoint</string> <string name="waypoint_note">Nota</string> <string name="waypoint_visited">Visitado</string> <string name="waypoint_save">Guardar</string> - <string name="waypoint_loading">Cargando punto de referencia…</string> - <string name="waypoint_do_not_touch_cache_coordinates">No cambiar las coordenadas del cache</string> - <string name="waypoint_set_as_cache_coords">Establecer como coordenadas del cache solo en c:geo</string> - <string name="waypoint_save_and_modify_on_website">Establecer como coordenadas del cache en c:geo y en la web</string> - <string name="waypoint_reset_cache_coords">Restablecer las coordenadas del cache</string> - <string name="waypoint_coordinates_has_been_reset_on_website">Las coordenadas del cache han sido reseteadas en la web.</string> - <string name="waypoint_coordinates_being_reset_on_website">Reseteando las coordenadas del cache en la web...</string> + <string name="waypoint_cancel_edit">Cancelar</string> + <string name="waypoint_loading">Cargando waypoint…</string> + <string name="waypoint_do_not_touch_cache_coordinates">No cambiar las coordenadas del caché</string> + <string name="waypoint_set_as_cache_coords">Establecer como coordenadas del caché en c:geo</string> + <string name="waypoint_save_and_modify_on_website">Establecer como coordenadas del caché en c:geo y en la web</string> + <string name="waypoint_reset_cache_coords">Restablecer las coordenadas del caché</string> + <string name="waypoint_coordinates_has_been_reset_on_website">Las coordenadas del caché han sido reseteadas en la web.</string> + <string name="waypoint_coordinates_being_reset_on_website">Reseteando las coordenadas del caché en la web…</string> <string name="waypoint_reset">Restablecer</string> <string name="waypoint_localy_reset_cache_coords">Restablecer en c:geo</string> <string name="waypoint_reset_local_and_remote_cache_coords">Restablecer en c:geo y en la web</string> <string name="waypoint_being_saved">Se está guardando el waypoint…</string> <string name="waypoint_coordinates_couldnt_be_modified_on_website">El sitio web no permite modificar las coordenadas del caché.</string> <string name="waypoint_coordinates_upload_error">Ha ocurrido un error mientras se modificaban las coordenadas en la web.</string> - <string name="waypoint_coordinates_uploading_to_website">Subiendo coordenadas a la página %s.</string> - <string name="waypoint_coordinates_has_been_modified_on_website">Las coordenadas del cache en la web modificadas a: %s.</string> + <string name="waypoint_coordinates_uploading_to_website">Subiendo coordenadas %s a la web.</string> + <string name="waypoint_coordinates_has_been_modified_on_website">Las coordenadas del caché en la web modificadas a: %s.</string> <string name="waypoint_done">Hecho</string> <string name="waypoint_duplicate">Duplicar</string> <string name="waypoint_copy_of">Copia de</string> @@ -752,43 +791,45 @@ <string name="search_clear_history">Borrar historial</string> <string name="search_history_cleared">Historial borrado</string> <string name="waypoint_coordinate_formats_plain">Sencillo</string> + <string name="from_clipboard">Desde portapapeles</string> + <string name="copy_to_clipboard">Copiar al portapapeles</string> <string name="visit_tweet">Publicar en Twitter</string> <string name="map_map">Mapa</string> <string name="map_live">Mapa activo</string> - <string name="map_view_map">Ver mapa</string> - <string name="map_modes">Configuración del mapa</string> + <string name="map_view_map">Elegir mapa</string> + <string name="map_modes">Ajustes del mapa</string> <string name="map_trail_show">Mostrar rastro</string> <string name="map_circles_show">Mostrar cÃrculos</string> - <string name="map_mycaches_hide">Esconder cachés propios/encontrados</string> + <string name="map_mycaches_hide">Ocultar propios/encontr.</string> <string name="map_theme_builtin">Por defecto</string> <string name="map_theme_select">Seleccionar tema del mapa</string> <string name="map_live_enable">Activar en vivo</string> <string name="map_live_disable">Desactivar en vivo</string> <string name="map_static_title">Mapas estáticos</string> <string name="map_static_loading">Cargando mapas estáticos…</string> - <string name="map_token_err">Dado que c:geo sólo es capaz de descargar datos parciales, la coordenadas de algunso escondites pueden ser inexactas.</string> + <string name="map_token_err">Dado que c:geo sólo es capaz de descargar datos parciales, la coordenadas de algunos cachés pueden ser inexactas.</string> <string name="map_as_list">Mostrar como lista</string> <string name="map_strategy">Estrategia</string> - <string name="map_strategy_title">Estrategia de mapa en directo</string> + <string name="map_strategy_title">Estrategia de mapa activo</string> <string name="map_strategy_fastest">Más rápido</string> <string name="map_strategy_fast">Rápido</string> <string name="map_strategy_auto">En función de la velocidad</string> <string name="map_strategy_detailed">Detallado</string> <string name="live_map_notification">Las coordenadas en el mapa en vivo pueden no ser precisas. Posibles coordenadas imprecisas están marcadas con un cÃrculo naranja.\nAbrir los detalles del caché o guardándolo para su uso sin conexión proporcionará siempre coordenadas precisas.\n\nPuedes encontrar más información en la página \"Sobre c:geo\" dentro de la app.</string> - <string name="search_bar_hint">Buscar escondites</string> - <string name="search_bar_desc">Escondites (Código-GC, palabra clave), Rastreables (Código-TB)</string> + <string name="search_bar_hint">Buscar cachés</string> + <string name="search_bar_desc">Cachés (Código-GC, palabra clave), Rastreables (Código-TB)</string> <string name="search_coordinates">Coordenadas</string> <string name="search_coordinates_button">Buscar por coordenadas</string> <string name="search_address">Dirección</string> <string name="search_address_button">Buscar por dirección</string> - <string name="search_geo">Geocode</string> + <string name="search_geo">Código GC</string> <string name="search_geo_button">Buscar por código</string> <string name="search_kw">Palabras clave</string> - <string name="search_kw_prefill">palabra clave</string> + <string name="search_kw_prefill">Palabra clave</string> <string name="search_kw_button">Buscar por palabra clave</string> - <string name="search_fbu">Encontrar por usuario</string> + <string name="search_fbu">Encontrados por usuario</string> <string name="search_fbu_prefill">Nombre de usuario</string> - <string name="search_fbu_button">Buscar por nombre de usuario</string> + <string name="search_fbu_button">Buscar por usuario</string> <string name="search_hbu">Oculto por usuario</string> <string name="search_hbu_prefill">Propietario</string> <string name="search_hbu_button">Buscar por propietario</string> @@ -807,35 +848,36 @@ <string name="trackable_details_loading">Cargando detalles del rastreable…</string> <string name="trackable_log_touch">Registrar contacto</string> <string name="trackable_browser_open">Abrir en navegador</string> - <string name="trackable_goal">Meta</string> + <string name="trackable_goal">Objetivo</string> <string name="trackable_details">Detalles</string> <string name="trackable_image">Imagen</string> - <string name="trackable_code">Código TB</string> + <string name="trackable_code">Código rastreable</string> <string name="trackable_name">Nombre</string> <string name="trackable_type">Tipo</string> <string name="trackable_owner">Propietario</string> - <string name="trackable_spotted">Marcado</string> + <string name="trackable_spotted">Visto</string> <string name="trackable_spotted_in_cache">En</string> <string name="trackable_spotted_at_user">En manos de</string> <string name="trackable_spotted_unknown_location">Ubicación desconocida</string> <string name="trackable_spotted_owner">En manos del propietario</string> <string name="trackable_origin">Origen</string> <string name="trackable_unknown">Desconocido</string> - <string name="trackable_released">Publicado</string> + <string name="trackable_released">Activado</string> <string name="trackable_distance">Recorrido</string> <string name="trackable_touch">Contacto</string> <string name="trackable_not_activated">Rasteable no activado</string> + <string name="trackable_geokrety">Geokrety</string> <string name="geokret_type_traditional">Tradicional</string> <string name="geokret_type_book_or_media">Libro o medio electrónicos</string> <string name="geokret_type_human">Humano</string> <string name="geokret_type_coin">Moneda</string> <string name="geokret_type_post">Correo</string> - <string name="user_menu_title">Acerca</string> - <string name="user_menu_view_hidden">Escondites ocultos</string> - <string name="user_menu_view_found">Escondites encontrados</string> + <string name="user_menu_title">Sobre</string> + <string name="user_menu_view_hidden">Cachés escondidos</string> + <string name="user_menu_view_found">Cachés encontrados</string> <string name="user_menu_open_browser">Abrir perfil en el navegador</string> <string name="user_menu_send_message">Enviar mensaje</string> - <string name="user_menu_open_contact">Abriendo tarjeta de contacto</string> + <string name="user_menu_open_contact">Abriendo contacto</string> <string name="navigation">Navegación</string> <string name="compass_title">Brújula</string> <string name="compass_sensors">Sensores activos</string> @@ -850,13 +892,13 @@ <string name="license_dismiss">Descartar</string> <string name="helper_calendar_title">Complemento de calendario de c:geo</string> <string name="helper_calendar_missing">Complemento de calendario de c:geo no está instalado.</string> - <string name="helper_calendar_description">Permite exportar caches evento al calendario de tu dispositivo.</string> + <string name="helper_calendar_description">Permite exportar eventos al calendario de tu dispositivo.</string> <string name="helper_sendtocgeo_title">Send to c:geo</string> <string name="helper_contacts_title">Complemento de contactos de c:geo</string> - <string name="helper_contacts_description">Permite abrir un contacto (de tu libreta de contactos) directamente desde un registro, para que puedas pedir ayuda a tus amigos más facilmente.</string> + <string name="helper_contacts_description">Permite abrir un contacto (de tu libreta de contactos) directamente desde un registro, para que puedas pedir ayuda a tus amigos más fácilmente.</string> <string name="helper_sendtocgeo_description">\'Enviar a c:geo\' es una extensión <strong>para tu PC</strong>. Cuando navegues por geocaching.com, puedes enviar cachés a tu smartphone haciendo clic directamente desde tu navegador.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Sencilla aplicación que muestra mapas en lÃnea y permite descargarlos para ser usados sin conexión (sólo mapas no vectoriales). También permite registrar el recorrido, gestionar puntos de interés y más funciones interesantes.</string> + <string name="helper_locus_description">App de navegación exterior para tu móvil o tableta. Puede visualizar mapas Topo sin conexión, marcar tu ruta, buscar geocachés, usar una guÃa de voz y mucho más.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Puedes usar el radar de esta aplicación con c:geo. Además ofrece un montón de información relacionada con el GPS.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -899,7 +941,7 @@ <string name="attribute_campfires_yes">Hogueras permitidas</string> <string name="attribute_campfires_no">Hogueras no permitidas</string> <string name="attribute_rv_yes">Camión/remolque permitido</string> - <string name="attribute_rv_no">camión/remolque no permitido</string> + <string name="attribute_rv_no">Camión/remolque no permitido</string> <string name="attribute_kids_yes">Recomendado para niños</string> <string name="attribute_kids_no">No recomendado para niños</string> <string name="attribute_onehour_yes">Se hace en menos de una hora</string> @@ -926,8 +968,8 @@ <string name="attribute_firstaid_no">No necesita mantenimiento</string> <string name="attribute_cow_yes">Hay que tener cuidado con el ganado</string> <string name="attribute_cow_no">No hay que tener cuidado con el ganado</string> - <string name="attribute_field_puzzle_yes">Terreno enrevesado</string> - <string name="attribute_field_puzzle_no">Terreno no enrevesado</string> + <string name="attribute_field_puzzle_yes">Puzzle en el lugar</string> + <string name="attribute_field_puzzle_no">No es puzzle en el lugar</string> <string name="attribute_nightcache_yes">Caché nocturno</string> <string name="attribute_nightcache_no">Caché no nocturno</string> <string name="attribute_parkngrab_yes">Se puede aparcar justo al lado</string> @@ -950,8 +992,8 @@ <string name="attribute_teamwork_no">No es necesario trabajo en equipo</string> <string name="attribute_landf_yes">Viaje perdidos y encontrados</string> <string name="attribute_landf_no">No viaje perdidos y encontrados</string> - <string name="attribute_partnership_yes">Escondite asociado</string> - <string name="attribute_partnership_no">Escondite no asociado</string> + <string name="attribute_partnership_yes">Caché asociado</string> + <string name="attribute_partnership_no">No es un caché asociado</string> <string name="attribute_fee_yes">Cuota de aparcamiento o acceso requerida</string> <string name="attribute_fee_no">Cuota de aparcamiento o acceso no requerida</string> <string name="attribute_rappelling_yes">Material de escalada necesario</string> @@ -982,8 +1024,8 @@ <string name="attribute_ticks_no">No hay garrapatas</string> <string name="attribute_mine_yes">Minas abandonadas</string> <string name="attribute_mine_no">No hay minas abandonadas</string> - <string name="attribute_cliff_yes">Precipicio /Caida de rocas</string> - <string name="attribute_cliff_no">No hay peligro de precipicio o caida de rocas</string> + <string name="attribute_cliff_yes">Precipicio/CaÃda de rocas</string> + <string name="attribute_cliff_no">No hay peligro de precipicio o caÃda de rocas</string> <string name="attribute_hunting_yes">CacerÃa</string> <string name="attribute_hunting_no">No hay cacerÃas</string> <string name="attribute_danger_yes">Zona peligrosa</string> @@ -1052,13 +1094,13 @@ <string name="attribute_all_seasons_no">No todas las estaciones</string> <string name="attribute_breeding_yes">Época de crÃa / Naturaleza protegida</string> <string name="attribute_breeding_no">No es época de crÃa / naturaleza protegida</string> - <string name="attribute_snow_proof_yes">Escondite a prueba de nieve</string> - <string name="attribute_snow_proof_no">Escondite NO a prueba de nieve</string> + <string name="attribute_snow_proof_yes">Caché a prueba de nieve</string> + <string name="attribute_snow_proof_no">No es caché a prueba de nieve</string> <string name="attribute_compass_yes">Brújula</string> <string name="attribute_compass_no">Sin brújula</string> <string name="attribute_cave_yes">Equipo para cuevas</string> <string name="attribute_cave_no">Sin equipo para cuevas</string> - <string name="attribute_aircraft_yes">Avión</string> + <string name="attribute_aircraft_yes">Aeronave</string> <string name="attribute_aircraft_no">No aeronave</string> <string name="attribute_investigation_yes">Investigación</string> <string name="attribute_investigation_no">No requiere investigar</string> @@ -1068,8 +1110,8 @@ <string name="attribute_arithmetic_no">No es un problema aritmético</string> <string name="attribute_other_cache_yes">Caché de otro tipo</string> <string name="attribute_other_cache_no">No es caché de otro tipo</string> - <string name="attribute_ask_owner_yes">Pregunta al propietario las coordendanas de inicio</string> - <string name="attribute_ask_owner_no">No es necesario preguntar al propietario las coordendas de inicio</string> + <string name="attribute_ask_owner_yes">Pregunta al propietario las condiciones iniciales</string> + <string name="attribute_ask_owner_no">No es necesario preguntar al propietario las condiciones iniciales</string> <string name="attribute_unknown_yes">Hay un atributo desconocido</string> <string name="attribute_unknown_no">No hay atributo desconocido</string> <string name="attribute_geotour_yes">Parte de un GeoTour</string> @@ -1107,12 +1149,15 @@ <string name="attribute_offset_cache_yes">Caché offset</string> <string name="attribute_offset_cache_no">No es caché offset</string> <string name="quote">Para hacer el geocaching más sencillo, para hacer a los usuarios más vagos.</string> - <string name="support">Soporte: <a href="">support@cgeo.org</a></string> - <string name="website">Web: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo en Google Play</a></string> - <string name="about_twitter">¿Debe <b>c:geo</b> publicar el nuevo estado en Twitter cuando registras un escondite?</string> + <string name="support_title">Soporte técnico</string> + <string name="website_title">Sitio Web</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">Página de c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo en Google Play</a></string> + <string name="about_twitter">¿Debe <b>c:geo</b> publicar el nuevo estado en Twitter cuando registras un caché?</string> + <string name="faq_title">Preguntas frecuentes</string> <string name="status_new_release" tools:ignore="UnusedResources">Nueva versión disponible. \nClick para instalar.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nueva versión nightly build disponible.\nHaz clic para instalar.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nueva versión candidate disponible.\nHaz clic para instalar.</string> @@ -1150,23 +1195,31 @@ <string name="tts_oclock">%s en punto</string> <string name="clipboard_copy_ok">Copiado al portapapeles</string> <plurals name="days_ago"> - <item quantity="one">Ayer</item> - <item quantity="other">Hace %d dÃas</item> + <item quantity="one">ayer</item> + <item quantity="other">hace %d dÃas</item> </plurals> <plurals name="favorite_points"> <item quantity="one">%s favorito</item> <item quantity="other">%s favoritos</item> </plurals> - <string name="percent_favorite_points">% \ favoritos</string> + <string name="more_than_percent_favorite_points">> %d%% favoritos</string> <string name="cgeo_shortcut">Atajo de c:geo</string> <string name="create_shortcut">Crear atajo</string> <string name="send">Enviar</string> <string name="showcase_logcache_title">Enviar el registro</string> - <string name="showcase_logcache_text">Recuerda, muchos de los comandos están ahora el la barra de tÃtulo. Allà encontrarás el botón para enviar el registro terminado.</string> + <string name="showcase_logcache_text">Recuerda, muchos de los comandos están ahora en la barra de tÃtulo. Allà encontrarás el botón para enviar el registro terminado.</string> <string name="showcase_main_title">Menús nuevos</string> <string name="showcase_main_text">c:geo coloca ahora los elementos del menú en la barra de tÃtulo como otras apps modernas. Algunos elementos se esconden detrás del sÃmbolo de puntos. Presiona de manera larga para ver su descripción.</string> <string name="showcase_cachelist_title">Cambio entre listas</string> <string name="showcase_cachelist_text">Puedes cambiar entre tus listas de cachés haciendo clic sobre el nombre de la lista.</string> + <string name="showcase_compass_hint_title">Mostrar la pista</string> + <string name="showcase_compass_hint_text">Este nuevo elemento del menú puede darte una idea de dónde encontrar el caché - muestra la pista, si está disponible.</string> <string name="confirm_log_title">Tipo de registro inusual</string> - <string name="confirm_log_message">Quieres registrar \'%s\'. ¿Estás seguro?</string> + <string name="confirm_log_message">Vas a registrar \'%s\'. ¿Estás seguro?</string> + <string name="init_geokrety">Geokrety.org</string> + <string name="init_geokrety_login">Iniciar sesión en Geokrety.org</string> + <string name="init_connectorGeokretyActive">Rastreables de Geokrety</string> + <string name="init_summary_geokrety">Habilitar rastreables de Geokrety.org</string> + <string name="init_summary_geokrety_cache">Mejorar la velocidad de carga.</string> + <string name="init_summary_geokrety_account">No hay cuenta configurada.</string> </resources> diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index 0287b48..655c31a 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -5,7 +5,7 @@ <string name="cache">Cache</string> <string name="detail">Détails</string> <string name="search">Rechercher</string> - <string name="helpers">Aide à l\'installation</string> + <string name="helpers">Applications utiles</string> <string name="about">À propos de c:geo</string> <string name="latitude">Latitude</string> <string name="longitude">Longitude</string> @@ -74,12 +74,14 @@ <string name="log_tb_visit">Visité</string> <string name="log_tb_drop">Déposé ici</string> <string name="log_tb_changeall">Tout modifié</string> - <string name="log_save">Enregistrer</string> + <string name="log_save">Sauvegarder hors-ligne</string> <string name="log_saving">Enregistrement en cours…</string> <string name="log_saving_and_uploading">Envoi de la note et de l\'image…</string> <string name="log_clear">Effacer</string> <string name="log_post_not_possible">Chargement de la page…</string> + <string name="log_date_future_not_allowed">Les entrées de carnet dans le futur sont interdites.</string> <string name="log_add">Ajouter</string> + <string name="log_repeat">Recopier la dernière entrée</string> <string name="log_no_rating">Pas de note</string> <string name="log_stars_1_description">faible</string> <string name="log_stars_15_description">plutôt faible</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Mot de passe du carnet :</string> <string name="log_hint_log_password">Entrez votre mot de passe pour le carnet</string> <string name="log_oc_team_comment">Commentaire de l\'équipe OC</string> + <string name="log_your_saved_log">Votre journal enregistré</string> <string-array name="log_image_scales"> <item>Taille originale</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Pas d\'utilisateur ou de mot de passe enregistré</string> <string name="err_login_failed_toast">c:geo est en mode hors-ligne et ne peut pas se connecter. Vérifiez votre connexion Internet.</string> <string name="err_unknown">Erreur inconnue</string> + <string name="err_unknown_address">c:geo n\'a pas réussi à trouver de coordonnées géographiques pour cette adresse</string> <string name="err_comm">Erreur inconnue de communication</string> <string name="err_missing_auth">Nom d\'utilisateur ou mot de passe manquant.</string> <string name="err_wrong">Nom d\'utilisateur inconnu ou mauvais mot de passe</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">L\'acquisition d\'une nouvelle image pour la note a échoué.</string> <string name="err_tb_display">\"c:geo ne peut pas afficher l\'objet voyageur demandé. Est-ce vraiment un objet voyageur?</string> <string name="err_tb_details_open">c:geo ne peut pas ouvrir le détail de l\'objet voyageur.</string> - <string name="err_tb_forgot_saw">c:geo a oublié quel objet voyageur vous avez vu.</string> <string name="err_tb_find">c:geo ne peut pas trouver d\'objet voyageur.</string> <string name="err_tb_find_that">c:geo ne peut pas trouver cet objet voyageur.</string> <string name="err_waypoint_cache_unknown">c:geo ne sait pas à quel cache vous voulez ajouter une étape.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo ne peut pas savoir où vous êtes.</string> <string name="err_point_no_position_given_title">Information obligatoire</string> <string name="err_point_no_position_given">Remplissez au moins la latitude ou la longitude ou la distance et le relèvement. Vous pouvez aussi remplir tous les champs.</string> - <string name="err_point_curr_position_unavailable">c:geo ne connaît pas encore votre position. Veuillez patienter…</string> <string name="err_point_bear_and_dist_title">Besoin d\'aide?</string> <string name="err_point_bear_and_dist">Remplissez le relèvement et la distance. Le relèvement est l\'angle de 0 à 360 degrés par rapport au Nord. La distance est avec ou sans les unités.</string> <string name="err_log_load_data">c:geo ne peut pas charger les données pour enregistrer votre visite.</string> <string name="err_log_load_data_again">c:geo ne peut pas charger les données pour enregistrer votre visite. Essayer plus tard.</string> <string name="err_log_load_data_still">c:geo est en train de charger les données pour enregistrer votre visite. Veuillez patienter encore un peu.</string> - <string name="err_log_post_failed">Il semble que votre visite n\'a pas été enregistrée. Veuillez vérifier sur le site Geocaching.com.</string> - <string name="err_log_post_failed_ec">Il semble que votre visite n\'a pas été enregistrée. Veuillez vérifier sur le site Extremcaching.com.</string> - <string name="err_logimage_post_failed">Il semble que l\'envoi de l\'image ait échoué. Veuillez vérifier sur le site Geocaching.com.</string> + <string name="err_log_post_failed">Il semble que votre visite n\'ait pas été enregistrée. Veuillez vérifier sur le site web d\'origine de la géocache.</string> + <string name="err_logimage_post_failed">Il semble que l\'envoi de l\'image a échoué. Veuillez vérifier sur le site web d\'origine de la géocache.</string> <string name="err_search_address_forgot">c:geo a oublié l\'adresse recherchée.</string> <string name="err_parse_lat">c:geo n\'arrive pas à lire la latitude.</string> <string name="err_parse_lon">c:geo n\'arrive pas à lire la longitude.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Réseau</string> <string name="loc_fused">Fusionné</string> <string name="loc_low_power">Éco</string> + <string name="loc_home">Domicile</string> <string name="loc_gps">Gps</string> <string name="loc_sat">Satellites</string> <string name="loc_trying">Localisation en cours…</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Proches</string> <string name="advanced_search_button">Recherche</string> <string name="stored_caches_button">Stockées</string> - <string name="any_button">N\'importe</string> + <string name="any_button">Aller à </string> <string name="unknown_scan">Le scan ne trouve pas de géocode.</string> <string name="caches_no_cache">Aucune cache</string> <string name="caches_more_caches">Charger plus de caches</string> @@ -263,15 +265,22 @@ <string name="caches_sort_finds">Trouvées</string> <string name="caches_sort_state">État</string> <string name="caches_sort_storage">Date de sauvegarde dans l\'appareil</string> + <string name="caches_sort_eventdate">Date de l\'événement</string> <string name="caches_select_mode">Mode sélection</string> <string name="caches_select_mode_exit">Sortir du mode sélection</string> <string name="caches_select_invert">Inverser la sélection</string> <string name="caches_nearby">Proches</string> <string name="caches_manage">Gérer</string> <string name="caches_remove_all">Tout supprimer</string> - <string name="caches_remove_all_confirm">Voulez-vous supprimer les %s caches de votre liste actuelle ?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Voulez-vous supprimer cette cache de la liste actuelle ?</item> + <item quantity="other">Voulez vous supprimer ces %d caches de la liste actuelle ?</item> + </plurals> <string name="caches_remove_selected">Supprimer la sélection</string> - <string name="caches_remove_selected_confirm">Voulez-vous supprimer de votre appareil les %s caches sélectionnées ?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Voulez-vous supprimer cette cache de votre appareil ?</item> + <item quantity="other">Voulez-vous supprimer les %d caches sélectionnées de votre appareil ?</item> + </plurals> <string name="caches_remove_progress">Suppression des caches en cours</string> <string name="caches_delete_events">Effacer les événements précédents</string> <string name="caches_refresh_selected">Rafraîchir les caches sélectionnées</string> @@ -291,13 +300,18 @@ <string name="caches_filter_track">Avec des objets voyageurs</string> <string name="caches_filter_clear">Effacer les filtres</string> <string name="caches_filter_modified">Avec les coordonnées modifiées</string> + <string name="caches_filter_offline_log">Avec entrée de carnet hors connexion</string> <string name="caches_filter_origin">Avec les coordonées originales</string> <string name="caches_filter_distance">Distance</string> <string name="caches_filter_personal_note">Avec une note personnelle</string> <string name="caches_filter_popularity">Favoris</string> <string name="caches_filter_popularity_ratio">Favoris [%]</string> + <string name="caches_filter_personal_data">Avec des données personnelles</string> + <string name="caches_filter_rating">Ayant reçu une note</string> + <string name="caches_filter_own_rating">Ayant reçu une note de votre part</string> <string name="caches_removing_from_history">Effacer de l\'historique…</string> <string name="caches_clear_offlinelogs">Effacer les entrées de carnet hors-ligne</string> + <string name="caches_clear_offlinelogs_message">Effacer tous les journaux hors ligne ?</string> <string name="caches_clear_offlinelogs_progress">Effacement des entrées de carnet hors-ligne</string> <string name="list_menu_create">Nouvelle liste</string> <string name="list_menu_drop">Effacer la liste courante</string> @@ -320,13 +334,17 @@ <string name="list_not_available">La liste n\'est plus disponible, basculement vers la liste standard</string> <string name="about_version">Version</string> <string name="about_changelog">Versions</string> + <string name="about_system">Système</string> <string name="about_donate">Dons</string> <string name="about_donation_more">Don\ndéveloppement</string> <string name="about_contributors">Contributeurs</string> <string name="about_license">Licence</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Aide</string> + <string name="about_system_include">Merci d\'inclure systématiquement les informations suivantes lorsque vous signalez un problème ou demandez plus d\'information à propos de c:geo:</string> + <string name="changelog_github">Liste de toutes les modifications</string> <string name="settings_title_services">Services</string> + <string name="settings_summary_services">Configuration des données de connexion et des services optionnels.</string> <string name="settings_title_appearance">Apparence</string> <string name="settings_title_cachedetails">Détails de la cache</string> <string name="settings_title_offlinedata">Données hors-ligne</string> @@ -374,6 +392,9 @@ <string name="settings_activate_oc_uk">Activer</string> <string name="init_oc_uk_description">Autoriser c:geo à utiliser opencaching.org.uk pour chercher des caches et accéder/filtrer vos caches trouvées.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Pour pouvoir attribuer une note à une géocache, vous devez suivre les instructions de GCVote.com et entrer ici votre mot de passe GCVote.</string> + <string name="err_gcvote_send_rating">Erreur lors de l\'envoi de la note, vérifiez le mot de passe GCVote dans les paramètres ou effacez le.</string> + <string name="gcvote_sent">Note envoyée</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activer</string> <string name="init_username">Identifiant</string> @@ -444,6 +465,8 @@ <string name="init_backup_success">La base de données de c:geo a été sauvegardée dans un fichier</string> <string name="init_backup_failed">La sauvegarde de la base de données de c:geo a échouée.</string> <string name="init_backup_unnecessary">La base de données est vide, sauvegarde non nécessaire.</string> + <string name="backup_confirm_overwrite">Voulez-vous remplacer la sauvegarde existante de %s ?</string> + <string name="restore_confirm_overwrite">Voulez vous remplacer %s sur votre appareil par la sauvegarde ?</string> <string name="init_restore_success">Restauration terminée.</string> <string name="init_restore_failed">Échec de la restauration.</string> <string name="init_restore_running">Restauration de la base de données des caches…</string> @@ -602,6 +625,7 @@ </plurals> <string name="cache_waypoints_add">Ajouter une étape</string> <string name="cache_hint">Indice</string> + <string name="cache_hint_not_available">Aucun indice disponible</string> <string name="cache_logs">Carnet de bord</string> <string name="cache_logs_friends_and_own">Vous / amis</string> <string name="cache_dialog_loading_details">Chargement des détails…</string> @@ -641,9 +665,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Navigateur</string> <string name="cache_menu_visit">Carnet</string> - <string name="cache_menu_visit_offline">Enregistrer la visite hors-ligne</string> + <string name="cache_menu_visit_offline">Journal hors connexion en un clic</string> <string name="cache_menu_spoilers">Images indices</string> <string name="cache_menu_around">Alentours</string> + <string name="around">Autour de %s</string> <string name="cache_menu_event">Ajouter à l\'agenda</string> <string name="cache_menu_details">Détails</string> <string name="cache_menu_refresh">Recharger</string> @@ -653,6 +678,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Noter</string> + <string name="cache_menu_checker">Ouvrir le geovérificateur</string> + <string name="cache_menu_ignore">Ignorer la cache</string> <string name="cache_status">Statut</string> <string name="cache_status_offline_log">Visite sauvée hors-ligne</string> <string name="cache_status_found">Trouvée</string> @@ -738,6 +766,7 @@ <string name="waypoint_note">Note</string> <string name="waypoint_visited">Marquer comme visité</string> <string name="waypoint_save">Sauver</string> + <string name="waypoint_cancel_edit">Annuler</string> <string name="waypoint_loading">Chargement d\'une étape…</string> <string name="waypoint_do_not_touch_cache_coordinates">Ne pas modifier les coordonnées de la cache</string> <string name="waypoint_set_as_cache_coords">Utiliser comme coordonnées de la cache dans c:geo</string> @@ -762,6 +791,8 @@ <string name="search_clear_history">Effacer l\'historique</string> <string name="search_history_cleared">Historique effacé</string> <string name="waypoint_coordinate_formats_plain">Texte</string> + <string name="from_clipboard">Depuis le presse-papiers</string> + <string name="copy_to_clipboard">Copier dans le presse-papiers</string> <string name="visit_tweet">Publier votre découverte sur Twitter</string> <string name="map_map">Carte</string> <string name="map_live">Carte active</string> @@ -866,7 +897,7 @@ <string name="helper_contacts_description">Permet d\'ouvrir une fiche de contact (depuis le carnet d\'adresses) directement depuis une entrée de journal, de manière à pouvoir plus facilement appeler des amis à l\'aide.</string> <string name="helper_sendtocgeo_description">Envoyer à c:geo (<i>Send to c:geo</i>) est une extension pour le navigateur <strong>de votre ordinateur</strong>. Lorsque vous naviguez sur geocaching.com, vous pouvez envoyer des caches vers votre smartphone avec un clic.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Application simple affichant des cartes en ligne et hors ligne. Permet d\'enregistrer son parcours, de gérer des POI et de nombreuses autres fonctions utiles.</string> + <string name="helper_locus_description">Application pour la navigation en plein air pour téléphone ou tablette. Visualisez les cartes hors-lignes, enregistrez le chemin parcouru, cherchez les géocaches, utilisez le guidage vocal et plus.</string> <string name="helper_gpsstatus_title">Etat GPS</string> <string name="helper_gpsstatus_description">Vous pouvez utiliser le radar de cette application dans c:geo. Il gère des informations supplémentaires relatives au GPS.</string> <string name="helper_bluetoothgps_title">GPS Bluetooth</string> @@ -1118,13 +1149,15 @@ <string name="attribute_offset_cache_no">Pas de cache relative</string> <string name="quote">Pour faciliter le géocaching.</string> <string name="powered_by">carnero</string> - <string name="support">support: <a href="">support@cgeo.org</a></string> - <string name="website">site: <a href="">cgeo.org</a></string> - <string name="facebook">facebook: <a href="">page c:geo</a></string> - <string name="twitter">twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo sur Google Play</a></string> + <string name="support_title">Assistance</string> + <string name="website_title">Site web</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">Page de c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo sur Google Play</a></string> <string name="about_twitter">Voulez-vous publier un nouveau statut sur Twitter à chaque nouvelle cache découverte sous <b>c:geo</b>?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Nouvelle version disponible.\nCliquer pour installer.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nouvelle version de test disponible.\nCliquer pour installer.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nouvelle version candidate disponible.\nCliquer pour installer.</string> @@ -1169,7 +1202,7 @@ <item quantity="one">%s favori</item> <item quantity="other">%s favoris</item> </plurals> - <string name="percent_favorite_points">%\ favoris</string> + <string name="more_than_percent_favorite_points">> %d%% favoris</string> <string name="cgeo_shortcut">c:geo raccourci</string> <string name="create_shortcut">Créer un raccourci</string> <string name="send">Envoyer</string> @@ -1179,6 +1212,8 @@ <string name="showcase_main_text">c:geo place maintenant les entrées de menu dans la barre de titre. Certaines sont cachées derrière les trois points. Un appui long donne la description d\'un bouton.</string> <string name="showcase_cachelist_title">Changer de liste</string> <string name="showcase_cachelist_text">Vous pouvez basculer entre vos différentes listes en cliquant sur le nom de la liste courante.</string> + <string name="showcase_compass_hint_title">Afficher l\'indice</string> + <string name="showcase_compass_hint_text">Cette nouvelle entrée de menu peut vous aider à trouver la géocache - elle montre l\'indice, s\'il y en a un.</string> <string name="confirm_log_title">Type inhabituel d\'entrée de journal</string> <string name="confirm_log_message">Vous allez envoyer \'%s\'. Êtes-vous sûr(e) ?</string> </resources> diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml index 8352fb8..84a8658 100644 --- a/main/res/values-hu/strings.xml +++ b/main/res/values-hu/strings.xml @@ -15,9 +15,9 @@ <string name="multi">Multi-láda</string> <string name="mystery">Rejtvény láda</string> <string name="letterbox">Postaláda hibrid</string> - <string name="event">Esemény láda</string> - <string name="mega">Mega-esemény láda</string> - <string name="giga">Giga-esemény geoláda</string> + <string name="event">Esemény</string> + <string name="mega">Mega esemény</string> + <string name="giga">Giga esemény</string> <string name="earth">Earthcache</string> <string name="cito">CITO esemény</string> <string name="webcam">Webkamera láda</string> @@ -74,12 +74,13 @@ <string name="log_tb_visit">Látogatás</string> <string name="log_tb_drop">Ládába helyezés</string> <string name="log_tb_changeall">Az összes megváltoztatása</string> - <string name="log_save">Mentés</string> + <string name="log_save">Offline mentés</string> <string name="log_saving">Log mentése…</string> <string name="log_saving_and_uploading">Log beküldése és kép feltöltése…</string> <string name="log_clear">Törlés</string> <string name="log_post_not_possible">Log oldal betöltése…</string> <string name="log_add">Hozzáadás</string> + <string name="log_repeat">Utolsó log ismétlése</string> <string name="log_no_rating">Nincs értékelés</string> <string name="log_stars_1_description">nagyon rossz</string> <string name="log_stars_15_description">elég rossz</string> @@ -124,6 +125,7 @@ <string name="err_login">Nincs mentett belépési adat</string> <string name="err_login_failed_toast">Sajnos a c:geo nem tud belépni. A c:geo hálózat nélküli módban fut. EllenÅ‘rizd a belépési adataid a beállÃtásoknál vagy engedélyezd az internet kapcsolatot.</string> <string name="err_unknown">Ismeretlen hiba</string> + <string name="err_unknown_address">A c:geo nem tudta leképezni ezt a cÃmet egy létezÅ‘ helyszÃnre</string> <string name="err_comm">Ismeretlen kommunikációs hiba</string> <string name="err_missing_auth">Nincs megadva belépési név és/vagy jelszó.</string> <string name="err_wrong">Rossz belépési adatok</string> @@ -152,13 +154,12 @@ <string name="err_dwld_details_failed">Sajnáljuk, a c:geo nem tudja letölteni a láda adatait.</string> <string name="err_load_descr_failed">Sajnáljuk, a c:geo nem tudja betölteni a leÃrást.</string> <string name="err_location_unknown">A c:geo nem ismeri a láda helyét.</string> - <string name="err_missing_device_name">Kérlek, regisztráció elÅ‘tt Ãrd be az eszköz nevét.</string> + <string name="err_missing_device_name">Kérlek, regisztráció elÅ‘tt adj meg egy készüléknevet.</string> <string name="err_favorite_failed">Kedvenc állapotmódosÃtása nem sikerült.</string> <string name="err_select_logimage_failed">Kép kiválasztása sikertelen.</string> <string name="err_acquire_image_failed">A kép készÃtése nem sikerült.</string> <string name="err_tb_display">Sajnáljuk, a c:geo nem tudja megjelenÃteni a követhetÅ‘ tárgyat. Biztos, hogy ez egy követhetÅ‘ tárgy?</string> <string name="err_tb_details_open">Sajnáljuk, a c:geo nem tudja megnyitni a követhetÅ‘ tárgy leÃrását.</string> - <string name="err_tb_forgot_saw">Sajnáljuk, a c:geo elfelejtette, melyik követhetÅ‘ tárgyat láttad.</string> <string name="err_tb_find">Sajnáljuk, a c:geo nem találja a követhetÅ‘ tárgyat.</string> <string name="err_tb_find_that">Sajnáljuk, a c:geo nem találja azt a követhetÅ‘ tárgyat.</string> <string name="err_waypoint_cache_unknown">Sajnáljuk, a c:geo nem tudja melyik ládához szeretnéd hozzáadni az útpontot.</string> @@ -166,15 +167,13 @@ <string name="err_point_unknown_position">Sajnáljuk, a c:geo nem tudja felismerni hol vagy.</string> <string name="err_point_no_position_given_title">Információ szükséges</string> <string name="err_point_no_position_given">Ãrd be legalább a szélességi és hosszúsági vagy a távolsági és irány értéket. Megadhatod mind a négyet is.</string> - <string name="err_point_curr_position_unavailable">A c:geo továbbra sem ismeri a jelenlegi koordinátákat. Kérlek várj egy ideig.</string> <string name="err_point_bear_and_dist_title">SegÃtségre van szükséged?</string> <string name="err_point_bear_and_dist">Tölsd ki az irányt és a távolságot is. Az irány az északkal bezárt szög 0 és 360 fok között. A távolság mértékegységgel és mértékegység nélkül is állhat.</string> <string name="err_log_load_data">Sajnáljuk, a c:geo nem tudja betölteni a megtalálás bejelentéséhez szükségesek adatokat.</string> <string name="err_log_load_data_again">Sajnáljuk, a c:geo nem tudja betölteni a megtalálás bejelentéséhez szükségesek adatokat. Újrapróbálkozás.</string> <string name="err_log_load_data_still">A c:geo még tölti a megtalálás bejelentéséhez szükségesek adatokat. Kérlek, várj egy kicsit tovább.</string> - <string name="err_log_post_failed">Úgy tűnik, a logod nem került hozzáadásra. Kérlek, ellenÅ‘rizd a geocaching.com-on.</string> - <string name="err_log_post_failed_ec">Úgy tűnik, hogy a logod nem került hozzáadásra. Kérlek, ellenÅ‘rizd a geocaching.com-on!</string> - <string name="err_logimage_post_failed">Úgy tűnik, hogy a log képed feltöltése nem sikerült. Kérjük, ellenÅ‘rizd a geocaching.com-on!</string> + <string name="err_log_post_failed">Úgy tűnik, hogy a logod nem ment át. Kérlek, ellenÅ‘rizd a láda eredeti oldalát.</string> + <string name="err_logimage_post_failed">Úgy tűnik, hogy a logfotóid nem mentek át. Kérlek, ellenÅ‘rizd a láda eredeti oldalát.</string> <string name="err_search_address_forgot">Sajnáljuk, a c:geo elfelejtette a keresett cÃmet.</string> <string name="err_parse_lat">Sajnáljuk, a c:geo nem tudja értelmezni a szélességet.</string> <string name="err_parse_lon">Sajnáljuk, a c:geo nem tudja értelmezni a hosszúságot.</string> @@ -210,6 +209,8 @@ <string name="loc_last">Utolsó ismert</string> <string name="loc_net">Hálózat</string> <string name="loc_fused">Kombinált</string> + <string name="loc_low_power">Takarékos üzemmód</string> + <string name="loc_home">Otthon koordinátái</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Műhold</string> <string name="loc_trying">Keresés folyamatban</string> @@ -223,12 +224,11 @@ <string name="menu_filter">SzűrÅ‘</string> <string name="menu_scan_geo">Geokód szkennelése</string> <string name="menu_pocket_queries">Pocket lekérdezések</string> - <string name="menu_scan_description">A c:geo QR formátumó geokódokat is be tud olvasni, de az ehhez szükséges alkalmazás nincs telepÃtve. Szeretné megnyitni a Google Play-t, hogy telepÃtse?</string> + <string name="menu_scan_description">A c:geo QR formátumú geokódokat is be tud olvasni, de az ehhez szükséges alkalmazás nincs telepÃtve. Szeretné megnyitni a Google Play-t, hogy telepÃtse?</string> <string name="live_map_button">ÉlÅ‘ térkép</string> <string name="caches_nearby_button">A közelben</string> <string name="advanced_search_button">Keresés</string> <string name="stored_caches_button">Mentett</string> - <string name="any_button">Szabad cél</string> <string name="unknown_scan">Nem található geokód a scannelés eredményében.</string> <string name="caches_no_cache">Nem található láda</string> <string name="caches_more_caches">Nem elég? Keress több ládát!</string> @@ -254,23 +254,29 @@ <string name="caches_sort_favorites_ratio">kedvencek [%]</string> <string name="caches_sort_name">név</string> <string name="caches_sort_geocode">GC-kód</string> - <string name="caches_sort_rating">osztályzat</string> - <string name="caches_sort_vote">szavazat (saját osztályzat)</string> + <string name="caches_sort_rating">értékelés</string> + <string name="caches_sort_vote">szavazat (saját értékelés)</string> <string name="caches_sort_inventory">tárgyak száma</string> <string name="caches_sort_date_hidden">rejtés dátuma</string> <string name="caches_sort_date_logged">log dátuma</string> <string name="caches_sort_finds">megtalálások</string> <string name="caches_sort_state">állapot</string> - <string name="caches_sort_storage">Az eszközön tárolt dátum</string> + <string name="caches_sort_storage">A készüléken tárolt dátum</string> <string name="caches_select_mode">Kiválasztó mód</string> <string name="caches_select_mode_exit">Kilépés a kiválasztó módból</string> <string name="caches_select_invert">Kijelölés megfordÃtása</string> <string name="caches_nearby">Közeli</string> <string name="caches_manage">Kezelés</string> <string name="caches_remove_all">Összes eltávolÃtása</string> - <string name="caches_remove_all_confirm">Szeretnéd eltávolÃtani az összes (%s) ládát a jelenlegi csoportból?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">El akarod távolÃtani ezt a ládát az aktuális listából?</item> + <item quantity="other">El akarod távolÃtani a(z) %d ládát az aktuális listából?</item> + </plurals> <string name="caches_remove_selected">Kijelölt ládák eltávolÃtása</string> - <string name="caches_remove_selected_confirm">Szeretnéd a kijelölt %s ládát törölni az eszközödrÅ‘l?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">El akarod távolÃtani ezt a ládát a készülékedrÅ‘l?</item> + <item quantity="other">El akarod távolÃtani a kijelölt %d ládát a készülékedrÅ‘l?</item> + </plurals> <string name="caches_remove_progress">Ládák törlése</string> <string name="caches_delete_events">Korábbi események törlése</string> <string name="caches_refresh_selected">Kijelöltek frissÃtése</string> @@ -285,18 +291,22 @@ <string name="caches_recaptcha_continue">Folytatás</string> <string name="caches_filter">SzűrÅ‘</string> <string name="caches_filter_title">Szűrés eszerint</string> - <string name="caches_filter_size">méret</string> - <string name="caches_filter_type">tÃpus</string> - <string name="caches_filter_track">követhetÅ‘ tárgyak</string> - <string name="caches_filter_clear">szűrÅ‘k törlése</string> - <string name="caches_filter_modified">MódosÃtott koordinátákkal</string> + <string name="caches_filter_size">Méret</string> + <string name="caches_filter_type">TÃpus</string> + <string name="caches_filter_track">KövethetÅ‘ tárgyak</string> + <string name="caches_filter_clear">SzűrÅ‘k törlése</string> + <string name="caches_filter_modified">MódosÃtott koordináták</string> <string name="caches_filter_origin">Származás</string> <string name="caches_filter_distance">Távolság</string> - <string name="caches_filter_personal_note">Személyes megjegyzéssel ellátottak</string> + <string name="caches_filter_personal_note">Személyes megjegyzés</string> <string name="caches_filter_popularity">Kedvencek</string> <string name="caches_filter_popularity_ratio">Kedvencek [%]</string> + <string name="caches_filter_personal_data">Személyes adatok</string> + <string name="caches_filter_rating">Értékelés</string> + <string name="caches_filter_own_rating">Saját értékelés</string> <string name="caches_removing_from_history">EltávolÃtás a ElÅ‘zményekbÅ‘l…</string> <string name="caches_clear_offlinelogs">Offline logok törlése</string> + <string name="caches_clear_offlinelogs_message">Szeretnéd törölni az offline logokat?</string> <string name="caches_clear_offlinelogs_progress">Offline logok törlése folyamatban</string> <string name="list_menu_create">Új lista létrehozása</string> <string name="list_menu_drop">Jelenlegi lista elvetése</string> @@ -319,13 +329,16 @@ <string name="list_not_available">A csoport már nem elérhetÅ‘, váltás az alapértelmezett csoportra</string> <string name="about_version">Verzió</string> <string name="about_changelog">Változások</string> + <string name="about_system">Rendszer</string> <string name="about_donate">Adományozás</string> <string name="about_donation_more">Adomány\na fejlesztéshez</string> <string name="about_contributors">Hozzájárulók</string> <string name="about_license">Licensz</string> <string name="about_apache_license"><a href=""> Apache License, 2.0 verzió</a></string> <string name="about_help">SegÃtség</string> + <string name="about_system_include">Kérlek, csatold a következÅ‘ rendszerinformációt, ha hibajelentést küldesz, vagy további információt kérsz a c:geo-ról:</string> <string name="settings_title_services">Szolgáltatók</string> + <string name="settings_summary_services">A felhasználói fiók adatainak és a választható szolgáltatásokhoz való hozzáférés beállÃtása.</string> <string name="settings_title_appearance">MegjelenÃtés</string> <string name="settings_title_cachedetails">Geoláda részletek</string> <string name="settings_title_offlinedata">Offline adatok</string> @@ -373,6 +386,9 @@ <string name="settings_activate_oc_uk">Aktiválás</string> <string name="init_oc_uk_description">c:geo engedélyezése az opencaching.org.uk-ra, hogy geoládákat kereshessen és hozzáférhessen ill. szűrhessen a megtalált geoládáidra.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Ládák értékeléséhez kövesd az utasÃtásokat a GCVote.com-on és add meg itt a GCVote jelszavad.</string> + <string name="err_gcvote_send_rating">Sikertelen az értélkelés elküldése, ellenÅ‘rizd a GCVote jelszavad a beállÃtásoknál. Próbálkozz a törlésével.</string> + <string name="gcvote_sent">Az értékelés sikeresen elment</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktiválás</string> <string name="init_username">Felhasználónév</string> @@ -384,7 +400,7 @@ <string name="init_login_popup_failed">Belépés sikertelen.</string> <string name="init_login_popup_failed_reason">Belépés sikertelen, mert </string> <string name="init_login_popup_not_authorized">Nem engedélyezett</string> - <string name="init_login_popup_invalid_timestamp">A helyi idÅ‘ érvénytelen, állÃtsd be a telefon óráját</string> + <string name="init_login_popup_invalid_timestamp">A helyi idÅ‘ érvénytelen, állÃtsd be a készülék óráját</string> <string name="init_login_popup_invalid_token">Sikertelen engedélyezés, próbáld újra</string> <string name="settings_service_active">AktÃv</string> <string name="init_signature">AláÃrás</string> @@ -492,10 +508,17 @@ <string name="init_maintenance_directories_note">A c:geo az egyes geoládákhoz képeket, logokat és egyéb fájlokat tárol egy külön mappában. Bizonyos esetekben (pl. adatbázis importja vagy exportja) ez a mappa már fölösleges adatokat tartalmazhat, amelyek ezzel a funkcióval törölhetÅ‘k.</string> <string name="init_maintenance_directories">Szükségtelen fájlok törlése</string> <string name="init_location">Helymeghatározás</string> + <string name="init_location_note">A Google Play Szolgáltatásokat használó készülékeken a c:geo automatikusan egy jobb helymeghatározó technikát használ. Ez azonban lehetetlenné teszi külsÅ‘, BlueTooth-os GPS vevÅ‘ alkalmazását.</string> <string name="init_location_googleplayservices">Google Play Szolgáltatások használata</string> + <string name="init_low_power">Takarékos üzemmód</string> + <string name="init_low_power_note">A takarékos üzemmód nem használja a GPS-t és a giroszkópot, emiatt a helymeghatározás lassabb és pontatlanabb.</string> + <string name="init_low_power_mode">Takarékos üzemmód indÃtása</string> <string name="init_create_memory_dump">Memóriatartalom mentése</string> <string name="init_memory_dump">Memóriatartalom</string> <string name="init_memory_dumped">Memóriatartalom mentve a %s-n</string> + <string name="init_hardware_acceleration_title">MegjelenÃtés hardveres gyorsÃtással</string> + <string name="init_hardware_acceleration_note">Hardveres gyorsÃtással gyorsabban jelennek meg a grafikus elemek a képernyÅ‘n. Azonban néhány készüléken az Android hibákat tartalmaz és némely szöveg homályosan jelenhet meg (különösen a félkövér karakterek). Tiltsd le a hardveres gyorsÃtást, ha ezt tapasztalod.</string> + <string name="init_hardware_acceleration">Hardveres gyorsÃtás engedélyezése</string> <string name="settings_open_website">Weboldal megnyitása</string> <string name="settings_settings">BeállÃtások</string> <string name="settings_information">További információk</string> @@ -524,14 +547,14 @@ <string name="map_source_osm_offline">Offline</string> <string name="init_sendToCgeo">Küldés c:geo-nak</string> <string name="settings_info_send2cgeo_title">Információk a \'Küldés c:geo-nak\'-ról</string> - <string name="init_sendToCgeo_name">Az eszközöd neve</string> - <string name="init_sendToCgeo_description">A <b>\'Küldés c:geo-nak\'</b> segÃtségével közvetlenül a geocaching weboldalról tölthetsz le ládákat egy Firefox vagy Chrome modul segÃtségével. Regisztráció elÅ‘tt olvasd el a leÃrást <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Csak akkor kell regisztrálnod, ha a \'Küldés c:geo-nak\' modult használni akarod. A c:geo a regisztráció nélkül is működik.</string> + <string name="init_sendToCgeo_name">Készüléked neve</string> + <string name="init_sendToCgeo_description">A <b>send2c:geo</b> segÃtségével közvetlenül a geocaching weboldalról tölthetsz le ládákat egy Firefox vagy Chrome modul segÃtségével. Regisztráció elÅ‘tt olvasd el a leÃrást <a href="http://send2.cgeo.org/">http://send2.cgeo.org/</a>. Csak akkor kell regisztrálnod, ha a send2c:geo modult használni akarod. A c:geo a regisztráció nélkül is működik.</string> <string name="init_sendToCgeo_register">Regisztráció kérése</string> - <string name="init_sendToCgeo_registering">Az eszközöd regisztrációja a \'Küldés c:geo-nak\' modulhoz…</string> - <string name="init_sendToCgeo_register_ok">A regisztráció sikeres. A PIN kód ####. Használd ezt a kódot a c:geo weboldalán, hogy hozzáadd ezt az eszközt a böngészÅ‘höz.</string> + <string name="init_sendToCgeo_registering">Készüléked regisztrációja a send2c:geo modulhoz…</string> + <string name="init_sendToCgeo_register_ok">A regisztráció sikeres. A PIN kód ####. Használd ezt a kódot a c:geo weboldalán, hogy hozzáadd ezt a készüléket a böngészÅ‘höz.</string> <string name="init_sendToCgeo_register_fail">Regisztráció sikertelen.</string> - <string name="sendToCgeo_download_fail">A c:geo nem tudta letölteni a ládákat. Nincs internetkapcsolat vagy a \'Küldés c:geo-nak\' leállt.</string> - <string name="sendToCgeo_no_registration">A c:geo nem tudta letölteni a ládákat. A \'Küldés c:geo-nak\' regisztrációd lejárt. Kérlek regisztrálj a beállÃtásoknál.</string> + <string name="sendToCgeo_download_fail">A c:geo nem tudta letölteni a ládákat. Nincs internetkapcsolat vagy a send2c:geo leállt.</string> + <string name="sendToCgeo_no_registration">A c:geo nem tudta letölteni a ládákat. A send2c:geo regisztrációd lejárt. Kérlek, regisztrálj a beállÃtásoknál.</string> <string name="auth_twitter">Twitter</string> <string name="auth_authorize">Hozzáférés engedélyezése a c:geo-nak</string> <string name="auth_start">Engedélyezés indÃtása</string> @@ -566,7 +589,7 @@ <string name="cache_premium">Prémium</string> <string name="cache_attributes">Tulajdonságok</string> <string name="cache_inventory">Tárgyak</string> - <string name="cache_log_images_title">Bejegyzés kép</string> + <string name="cache_log_images_title">Logfotók</string> <string name="cache_log_image_default_title">Fotó</string> <string name="cache_personal_note">Személyes megjegyzés</string> <string name="cache_personal_note_edit">Szerkesztés</string> @@ -637,7 +660,7 @@ <string name="cache_menu_streetview">Utcanézet</string> <string name="cache_menu_browser">Megnyitás böngészÅ‘ben</string> <string name="cache_menu_visit">Megtalálás bejelentése</string> - <string name="cache_menu_visit_offline">Megtalálás bejelentése offline</string> + <string name="cache_menu_visit_offline">Offline log egy kattintással</string> <string name="cache_menu_spoilers">Spoiler képek</string> <string name="cache_menu_around">Közeli ládák</string> <string name="cache_menu_event">Hozzáadás a naptárhoz</string> @@ -649,6 +672,8 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble (okosóra)</string> + <string name="cache_menu_android_wear">Android Wear</string> + <string name="cache_menu_vote">Értékelés</string> <string name="cache_status">Ãllapot</string> <string name="cache_status_offline_log">Mentett bejegyzés</string> <string name="cache_status_found">Megtalált</string> @@ -666,7 +691,7 @@ <string name="cache_distance">Távolság</string> <string name="cache_difficulty">Nehézség</string> <string name="cache_terrain">Terep</string> - <string name="cache_rating">Osztályzat</string> + <string name="cache_rating">Értékelés</string> <string name="cache_own_rating">Saját értékelés</string> <string name="cache_rating_of">/</string> <string name="cache_favorite">Kedvenc</string> @@ -758,6 +783,7 @@ <string name="search_clear_history">ElÅ‘zmények törlése</string> <string name="search_history_cleared">ElÅ‘zmények törölve</string> <string name="waypoint_coordinate_formats_plain">Egyszerű</string> + <string name="from_clipboard">A vágólapról</string> <string name="visit_tweet">Twitteld ki ezt a megtalálást</string> <string name="map_map">Térkép</string> <string name="map_live">ÉlÅ‘ térkép</string> @@ -856,13 +882,13 @@ <string name="license_dismiss">ElutasÃtás</string> <string name="helper_calendar_title">c:geo naptár add-on</string> <string name="helper_calendar_missing">c:geo naptár add-on nincs telepÃtve.</string> - <string name="helper_calendar_description">LehetÅ‘vé teszi a geoládák exportálását az eszközöd naptárába.</string> + <string name="helper_calendar_description">Események exportálása a készüléked naptárába.</string> <string name="helper_sendtocgeo_title">Küldés a c:geo-ra</string> <string name="helper_contacts_title">c:geo kapcsolatok add-on</string> <string name="helper_contacts_description">LehetÅ‘vé teszi egy névjegy közvetlen megnyitását a log bejegyzésekbÅ‘l, Ãgy könnyebben segÃtséget tudsz kérni.</string> <string name="helper_sendtocgeo_description">A \'Küldés a c:geo-ra\' egy böngészÅ‘ bÅ‘vÃtmény <strong>PC-re</strong>. A geocaching.com böngészése közben, egy kattintással tudsz geoládákat küldeni az okostelefonodra.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Egyszerűen kezelhetÅ‘ alkalmazás online térképek megjelenÃtésére, amelyeket le is tud tölteni offline használatra (csak raszteres térképekkel működik). Támogatja a nyomvonalrögzÃtést, érdekes pontok kezelést és sok egyéb hasznos funkciót.</string> + <string name="helper_locus_description">Telefonodon, tableteden használható szabadtéri navigációs progi. Offline térképek használata, útvonal követése, ládavadászat, hangos útikalauz, stb.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">A programban található radart a c:geo-hoz is használhatod. Sok egyéb GPS-el kapcsolatos információt is megmutat.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1114,13 +1140,7 @@ <string name="attribute_offset_cache_no">Nem offset láda</string> <string name="quote">Az egyszerűbb ládázásért, a lustább játékosokért.</string> <string name="powered_by">carnero</string> - <string name="support">Támogatás: <a href="">support@cgeo.org</a></string> - <string name="website">Weboldal: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Androidra: <a href="">c:geo a Google Play-en</a></string> <string name="about_twitter">Akarod, hogy a <b>c:geo</b> új bejegyzést Ãrjon a Twitter-re, amikor megtalálsz egy ládát?</string> - <string name="faq">GYIK: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Új kiadás jelent meg.\nKattints a telepÃtéshez.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Új napi frissÃtés jelent meg.\nKattints a telepÃtéshez.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Új kiadás elÅ‘tti verzió jelent meg.\nKattints a telepÃtéshez.</string> @@ -1165,8 +1185,16 @@ <item quantity="one">%s kedvenc pont</item> <item quantity="other">%s kedvenc pont</item> </plurals> - <string name="percent_favorite_points">%\ kedvenc pont</string> + <string name="more_than_percent_favorite_points">> %d%% kedvenc pont</string> <string name="cgeo_shortcut">c:geo parancsikon</string> <string name="create_shortcut">Parancsikon létrehozása</string> <string name="send">Küldés</string> + <string name="showcase_logcache_title">Log küldése</string> + <string name="showcase_logcache_text">Ne feledd, sok parancs található a cÃmsorban. Ott találod a kész logot elküldÅ‘ gombot is.</string> + <string name="showcase_main_title">Új menük</string> + <string name="showcase_main_text">A c:geo is a cÃmsorban jelenÃti meg a menüelemeket más modern appokhoz hasonlóan. Néhány elemet a pontozott szimbólum mögött találsz. A gombokat hosszan lenyomva jelennek meg a hozzájuk tartozó leÃrások.</string> + <string name="showcase_cachelist_title">Listák váltása</string> + <string name="showcase_cachelist_text">Váltogathatsz a ládalistáid között a listák cÃmére kattintva.</string> + <string name="confirm_log_title">Különleges logtÃpus</string> + <string name="confirm_log_message">Logod a következÅ‘: \'%s\'. Biztosan ezt akarod?</string> </resources> diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index e079b1d..1a379ea 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">Visitato</string> <string name="log_tb_drop">Lasciato</string> <string name="log_tb_changeall">Cambia tutto</string> - <string name="log_save">Salva</string> + <string name="log_save">Salva offline</string> <string name="log_saving">Invio log…</string> <string name="log_saving_and_uploading">Invio log e immagine…</string> <string name="log_clear">Azzera</string> <string name="log_post_not_possible">Connessione…</string> + <string name="log_date_future_not_allowed">Non sono ammesse date future per i log.</string> <string name="log_add">Aggiungi</string> + <string name="log_repeat">Ripeti l\'ultimo log</string> <string name="log_no_rating">Nessun voto</string> <string name="log_stars_1_description">proprio brutto</string> <string name="log_stars_15_description">abbastanza brutto</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Log Password:</string> <string name="log_hint_log_password">Inserisci la password per il log</string> <string name="log_oc_team_comment">Commenti del Team OC</string> + <string name="log_your_saved_log">I tuoi log salvati</string> <string-array name="log_image_scales"> <item>Dimensioni originali</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Informazioni di login non memorizzate</string> <string name="err_login_failed_toast">c:geo non può effettuare login. Attivata la modalità offline. Verificare le informazioni di login nelle impostazioni o abilitare una connessione internet.</string> <string name="err_unknown">Errore sconosciuto</string> + <string name="err_unknown_address">c:geo non è in grado di mappare questo indirizzo su una posizione gps esistente</string> <string name="err_comm">Errore sconosciuto di comunicazione</string> <string name="err_missing_auth">username e/o password non settati.</string> <string name="err_wrong">Informazioni di login errate</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Acquisizione immagine fallita.</string> <string name="err_tb_display">c:geo non riesce a visualizzare il trackable che vuoi. È veramente un trackable?</string> <string name="err_tb_details_open">c:geo non riesce ad aprire i dettagli del trackable.</string> - <string name="err_tb_forgot_saw">c:geo ha dimenticato quale trackable vedevi.</string> <string name="err_tb_find">c:geo non trova nessun trackable</string> <string name="err_tb_find_that">c:geo non trova quel trackable.</string> <string name="err_waypoint_cache_unknown">c:geo non conosce a quale cache vuoi aggiungere un waypoint.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo non capisce dove ti trovi.</string> <string name="err_point_no_position_given_title">Info richieste</string> <string name="err_point_no_position_given">Inserisci almeno latitudine e longitudine, o distanza e angolo. Puoi anche inserire tutti e quattro i valori.</string> - <string name="err_point_curr_position_unavailable">c:geo non ha le coordinate attuali. Attendere, prego…</string> <string name="err_point_bear_and_dist_title">Necessiti di aiuto?</string> <string name="err_point_bear_and_dist">Inserisci angolo e distanza. Angolo specifica un valore in gradi tra 0 e 360 relativo al nord. La distanza non richiede unità di misura.</string> <string name="err_log_load_data">c:geo non riesce a caricare i dati necessari per salvare il log della tua visita.</string> <string name="err_log_load_data_again">c:geo non riesce a caricare i dati necessari per salvare il log della tua visita. Nuovo tentativo in corso.</string> <string name="err_log_load_data_still">c:geo sta ancora caricando i dati necessari per salvare il log. Per cortesia attendere ancora un pochino.</string> - <string name="err_log_post_failed">Sembra che il log non sia stato inviato. Prego verificare su Geocaching.com.</string> - <string name="err_log_post_failed_ec">Sembra che il tuo log non sia stato pubblicato. Controlla su Extremcaching.com.</string> - <string name="err_logimage_post_failed">Sembra che l\'immagine del tuo log non sia stata caricata. Si prega di controllare su Geocaching.com.</string> + <string name="err_log_post_failed">Sembra che il log non sia stato pubblicato. Si prega di controllare sul sito Web del cache originario.</string> + <string name="err_logimage_post_failed">Sembra che l\'immagine del registro non sia stata caricata. Si prega di controllare sul sito Web del cache originario.</string> <string name="err_search_address_forgot">c:geo ha dimenticato l\'indirizzo che vuoi trovare.</string> <string name="err_parse_lat">c:geo non riesce ad interpretare la latitudine.</string> <string name="err_parse_lon">c:geo non riesce ad interpretare la longitudine.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Network</string> <string name="loc_fused">Combinato</string> <string name="loc_low_power">Risparmio energetico</string> + <string name="loc_home">Coordinate di casa</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Localizzazione in corso</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Vicini</string> <string name="advanced_search_button">Cerca</string> <string name="stored_caches_button">Salvati</string> - <string name="any_button">Ovunque</string> + <string name="any_button">Vai a</string> <string name="unknown_scan">Nessun geocode trovato nello scan.</string> <string name="caches_no_cache">Non ci sono cache</string> <string name="caches_more_caches">Carica altri cache</string> @@ -263,15 +265,18 @@ <string name="caches_sort_finds">Numero ritrovamenti</string> <string name="caches_sort_state">Stato</string> <string name="caches_sort_storage">Data salvataggio</string> + <string name="caches_sort_eventdate">Data Evento</string> <string name="caches_select_mode">Modo Selezione</string> <string name="caches_select_mode_exit">Esci dal modo Selezione</string> <string name="caches_select_invert">Inverti selezione</string> <string name="caches_nearby">Qui vicino</string> <string name="caches_manage">Gestisci</string> <string name="caches_remove_all">Elimina tutti</string> - <string name="caches_remove_all_confirm">Vuoi rimuovere tutti i %s cache dalla lista corrente?</string> <string name="caches_remove_selected">Elimina selezionati</string> - <string name="caches_remove_selected_confirm">Vuoi rimuovere i %s cache selezionati dal dispositivo?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Si desidera rimuovere questo cache dal tuo dispositivo?</item> + <item quantity="other">Vuoi rimuovere i %d cache selezionati dal dispositivo?</item> + </plurals> <string name="caches_remove_progress">Eliminazione dei cache</string> <string name="caches_delete_events">Cancella eventi passati</string> <string name="caches_refresh_selected">Aggiorna i cache selezionati</string> @@ -291,13 +296,18 @@ <string name="caches_filter_track">Con oggetti trackables</string> <string name="caches_filter_clear">Rimuovi filtri</string> <string name="caches_filter_modified">Con coordinate modificate</string> + <string name="caches_filter_offline_log">Con log offline</string> <string name="caches_filter_origin">Origine</string> <string name="caches_filter_distance">Distanza</string> <string name="caches_filter_personal_note">Con una nota personale</string> <string name="caches_filter_popularity">Preferiti</string> <string name="caches_filter_popularity_ratio">Preferiti [%]</string> + <string name="caches_filter_personal_data">Con dati personali</string> + <string name="caches_filter_rating">Con valutazione (rating)</string> + <string name="caches_filter_own_rating">Con propria valutazione (rating)</string> <string name="caches_removing_from_history">Rimozione dalla cronologia…</string> <string name="caches_clear_offlinelogs">Cancella i log offline</string> + <string name="caches_clear_offlinelogs_message">Vuoi cancellare tutti i log offline?</string> <string name="caches_clear_offlinelogs_progress">Cancellazione logs offline</string> <string name="list_menu_create">Crea nuova lista</string> <string name="list_menu_drop">Elimina la lista corrente</string> @@ -320,13 +330,17 @@ <string name="list_not_available">Elenco non più disponibile, passo a elenco standard</string> <string name="about_version">Versione</string> <string name="about_changelog">Modifiche</string> + <string name="about_system">Sistema</string> <string name="about_donate">Donazioni</string> <string name="about_donation_more">Fai una\nDonazione</string> <string name="about_contributors">Contributori</string> <string name="about_license">Licenza</string> <string name="about_apache_license"><a href="">Licenza Apache, versione 2.0</a></string> <string name="about_help">Guida</string> + <string name="about_system_include">Si prega di includere le seguenti informazioni di sistema quando si invia una segnalazione di bug o per chiedere ulteriori informazioni su c:geo:</string> + <string name="changelog_github">Elenco di tutte le modifiche</string> <string name="settings_title_services">Servizi</string> + <string name="settings_summary_services">Configura le informazioni utente dell\'account ed accede a servizi opzionali.</string> <string name="settings_title_appearance">Aspetto</string> <string name="settings_title_cachedetails">Dettagli cache</string> <string name="settings_title_offlinedata">Dati offline</string> @@ -370,6 +384,9 @@ <string name="settings_activate_oc_uk">Attiva</string> <string name="init_oc_uk_description">Autorizza c:geo a cercare cache ed accedere/filtrare i ritrovamenti su opencaching.org.uk.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Per poter votare un cache, è necessario seguire le istruzioni di GCVote.com e inserire la password di GCVote qui.</string> + <string name="err_gcvote_send_rating">Errore durante l\'invio del voto, verifica la password di GCVote nelle impostazioni oppure cancellala per disattivare GCVote.</string> + <string name="gcvote_sent">Voto inviato correttamente</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Attiva</string> <string name="init_username">Utente</string> @@ -440,6 +457,8 @@ <string name="init_backup_success">Il database di c:geo è stato salvato con successo nel file: </string> <string name="init_backup_failed">Backup del database di c:geo fallito.</string> <string name="init_backup_unnecessary">Il database è vuoto, il backup non è necessario.</string> + <string name="backup_confirm_overwrite">Vuoi sovrascrivere il backup esistente da %s?</string> + <string name="restore_confirm_overwrite">Vuoi sovrascrivere %s sul tuo dispositivo con il backup?</string> <string name="init_restore_success">Ripristino completato.</string> <string name="init_restore_failed">Ripristino fallito.</string> <string name="init_restore_running">Ripristino del database dei cache…</string> @@ -598,6 +617,7 @@ </plurals> <string name="cache_waypoints_add">Aggiungi waypoint</string> <string name="cache_hint">Aiuto (spoiler)</string> + <string name="cache_hint_not_available">Nessun aiuto disponibile</string> <string name="cache_logs">Logbook</string> <string name="cache_logs_friends_and_own">Log tuoi e degli amici</string> <string name="cache_dialog_loading_details">Caricamento dettagli del cache…</string> @@ -637,9 +657,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Apri nel browser</string> <string name="cache_menu_visit">Scrivi Log</string> - <string name="cache_menu_visit_offline">Scrivi Log offline</string> + <string name="cache_menu_visit_offline">Log offline con un solo click</string> <string name="cache_menu_spoilers">Immagini spoiler</string> <string name="cache_menu_around">Cache qui intorno</string> + <string name="around">Nei dintorni di %s</string> <string name="cache_menu_event">Aggiungi al calendario</string> <string name="cache_menu_details">Dettagli</string> <string name="cache_menu_refresh">Aggiorna</string> @@ -649,6 +670,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Vota</string> + <string name="cache_menu_checker">Open Geochecker</string> + <string name="cache_menu_ignore">Ignora cache</string> <string name="cache_status">Stato</string> <string name="cache_status_offline_log">Log salvato</string> <string name="cache_status_found">Trovato</string> @@ -734,6 +758,7 @@ <string name="waypoint_note">Note</string> <string name="waypoint_visited">Visitato</string> <string name="waypoint_save">Salva</string> + <string name="waypoint_cancel_edit">Annulla</string> <string name="waypoint_loading">Caricamento waypoint…</string> <string name="waypoint_do_not_touch_cache_coordinates">Nessuna modifica alle coordinate cache</string> <string name="waypoint_set_as_cache_coords">Setta come coordinate cache in c:geo</string> @@ -758,6 +783,8 @@ <string name="search_clear_history">Cancella cronologia</string> <string name="search_history_cleared">Cronologia azzerata</string> <string name="waypoint_coordinate_formats_plain">Plain</string> + <string name="from_clipboard">Dagli appunti</string> + <string name="copy_to_clipboard">Copia nella Clipboard</string> <string name="visit_tweet">Segnala questo ritrovamento su Twitter</string> <string name="map_map">Mappa</string> <string name="map_live">Mappa Live</string> @@ -862,7 +889,7 @@ <string name="helper_contacts_description">Consente di aprire una scheda contatto (della tua rubrica) direttamente da un log, per permetterti di chiedere aiuto agli amici più facilmente.</string> <string name="helper_sendtocgeo_description">Send to c:geo è un\'estensione del browser <strong>per il tuo PC</strong>. Durante la navigazione su geocaching.com, è possibile inviare i cache al vostro smartphone con il clic di un pulsante direttamente all\'interno del browser.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Applicazione semplice da usare che mostra mappe online permettendo di scaricarle direttamente per l\'uso offline (solo mappe raster). Supporta inoltra la registrazione di traccia, gestione dei waypoints e altre utili funzioni.</string> + <string name="helper_locus_description">App per la navigazione in esterni per cellulare o tablet. Mostra mappe offline, traccia il tuo percorso, cerca geocache, usa una voce guida e molto altro.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Puoi usare il radar di questa applicazione con c:geo. Offre inoltre molte informazioni addizionali legate al GPS.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1114,13 +1141,15 @@ <string name="attribute_offset_cache_no">Non è un offset cache</string> <string name="quote">Per rendere il geocaching più facile e gli utenti più pigri.</string> <string name="powered_by">carnero</string> - <string name="support">Supporto: <a href="">support@cgeo.org</a></string> - <string name="website">Sito: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">Pagina c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo su Google Play</a></string> + <string name="support_title">Aiuto</string> + <string name="website_title">Sito Internet</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">pagina c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo su Google Play</a></string> <string name="about_twitter">Può <b>c:geo</b> pubblicare su Twitter ogni volta che logghi un cache?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Una nuova versione è disponibile.\nClicca per installarla.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Una nuova versione nightly è disponibile.\nClicca per installarla.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Una nuova release candidate è disponibile.\nClicca per installarla.</string> @@ -1165,7 +1194,7 @@ <item quantity="one">%s preferito</item> <item quantity="other">%s preferiti</item> </plurals> - <string name="percent_favorite_points">%\ preferiti</string> + <string name="more_than_percent_favorite_points">> preferiti %d%%</string> <string name="cgeo_shortcut">collegamento a c:geo</string> <string name="create_shortcut">Crea collegamento</string> <string name="send">Invia</string> @@ -1175,6 +1204,8 @@ <string name="showcase_main_text">c:geo ora ha le voci di menu nella barra del titolo come altre moderne applicazioni. Alcuni elementi potrebbero essere nascosti dietro il simbolo dei puntini. Tenere premuto un bottone per vederne la descrizione.</string> <string name="showcase_cachelist_title">Cambio di liste</string> <string name="showcase_cachelist_text">Puoi cambiare la lista attiva cliccando sul titolo.</string> + <string name="showcase_compass_hint_title">Visualizza l\'hint</string> + <string name="showcase_compass_hint_text">Questo nuovo menu potrebbe darti un\'idea di dove si trova il cache. Mostra l\'hint, se disponibile.</string> <string name="confirm_log_title">Tipo di Log non usuale</string> <string name="confirm_log_message">Si desidera registrare \'%s\'. Sei sicuro?</string> </resources> diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml index 0a2b143..0fa8aa0 100644 --- a/main/res/values-ja/strings.xml +++ b/main/res/values-ja/strings.xml @@ -54,7 +54,7 @@ <string name="log_attend">å‚åŠ ã™ã‚‹</string> <string name="log_attended">å‚åŠ ã—ãŸ</string> <string name="log_retrieved">回åŽã—ãŸ</string> - <string name="log_placed">Placed</string> + <string name="log_placed">é…ç½®ã—ãŸ</string> <string name="log_grabbed">ã©ã“ã‹ã§æ•ã¾ãˆãŸ</string> <string name="log_movecollection">コレクションã«ç§»å‹•</string> <string name="log_moveinventory">目録ã«ç§»å‹•</string> @@ -70,8 +70,7 @@ <string name="log_tb_nothing">何もã—ãªã„</string> <string name="log_tb_visit">訪れãŸ</string> <string name="log_tb_drop">ã“ã“ã«ç½®ã</string> - <string name="log_tb_changeall">Change All</string> - <string name="log_save">ä¿å˜</string> + <string name="log_tb_changeall">ã™ã¹ã¦ã‚’変更ã™ã‚‹</string> <string name="log_saving">ãƒã‚°ã‚’é€ä¿¡ä¸â€¦</string> <string name="log_saving_and_uploading">ãƒã‚°ã¨ç”»åƒã‚’é€ä¿¡ä¸â€¦</string> <string name="log_clear">消去</string> @@ -101,8 +100,8 @@ <string name="log_image_caption">タイトル</string> <string name="log_image_description">説明</string> <string name="log_image_scale">拡大縮å°</string> - <string name="log_password_title">Log Password:</string> - <string name="log_hint_log_password">Enter your log password</string> + <string name="log_password_title">ãƒã‚°ã®ãƒ‘スワード:</string> + <string name="log_hint_log_password">パスワードを入力ã—ã¦ãã ã•ã„</string> <string-array name="log_image_scales"> <item>実サイズ</item> <item>512 px</item> @@ -126,7 +125,7 @@ <string name="err_maintenance">Geocaching.comã¯ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ä¸ã§æŽ¥ç¶šã§ãã¾ã›ã‚“。 ä¿å˜æ¸ˆã¿ã‚ャッシュã®ã¿ã§ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§å‹•ä½œã—ã¾ã™ã€‚</string> <string name="err_license">Geocaching.comã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹å¥‘ç´„ã«åŒæ„ã—ãªã‹ã£ãŸã®ã§ã‚ャッシュã®åº§æ¨™ã‚’見るã“ã¨ã¯ã§ãã¾ã›ã‚“。</string> <string name="err_unvalidated_account">Geocaching.comã§ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’有効化ã—ã¦ãã ã•ã„。</string> - <string name="err_unpublished">The requested cache is unpublished.</string> + <string name="err_unpublished">è¦æ±‚ã—ãŸã‚ャッシュãŒå…¬é–‹ã•ã‚Œã¦ã„ã¾ã›ã‚“。</string> <string name="err_premium_only">ã“ã®ã‚ャッシュã¯ãƒ—レミアム会員ã®ã¿æœ‰åŠ¹ã§ã™ã€‚</string> <string name="err_detail_open">ã‚ャッシュã®è©³ç´°ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“。</string> <string name="err_detail_cache">ã‚ãƒ£ãƒƒã‚·ãƒ¥æƒ…å ±ã‚’è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。ã“ã‚Œã¯æœ¬å½“ã«ã‚¸ã‚ªã‚ャッシュã§ã™ã‹?</string> @@ -138,7 +137,7 @@ <string name="err_detail_no_map_static">ã“ã®ã‚ャッシュã®ã‚ªãƒ•ãƒ©ã‚¤ãƒ³åœ°å›³ã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</string> <string name="err_detail_not_load_map_static">オフライン地図ã®ãƒãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</string> <string name="err_detail_still_working">ä»–ã®ã‚¿ã‚¹ã‚¯ãŒã¾ã 動作ä¸ã§ã™ã€‚</string> - <string name="err_watchlist_still_managing">Still managing your watchlist.</string> + <string name="err_watchlist_still_managing">ã¾ã ウォッãƒãƒªã‚¹ãƒˆã‚’管ç†ä¸ã§ã™ã€‚</string> <string name="err_watchlist_failed">ウォッãƒãƒªã‚¹ãƒˆã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</string> <string name="err_application_no">é©åˆ‡ãªã‚¢ãƒ—リケーションãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</string> <string name="err_auth_initialize">èªè¨¼ãƒ—ãƒã‚»ã‚¹ã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</string> @@ -154,24 +153,19 @@ <string name="err_acquire_image_failed">ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚</string> <string name="err_tb_display">トラッカブルを表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。本当ã«ãƒˆãƒ©ãƒƒã‚«ãƒ–ルã§ã™ã‹?</string> <string name="err_tb_details_open">トラッカブルã®è©³ç´°ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã›ã‚“。</string> - <string name="err_tb_forgot_saw">c:geo forgot which trackable you saw.</string> <string name="err_tb_find">トラッカブルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</string> <string name="err_tb_find_that">トラッカブルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</string> <string name="err_waypoint_cache_unknown">c:geo doesn\'t know to which cache you want to add waypoint.</string> <string name="err_waypoint_add_failed">ウェイãƒã‚¤ãƒ³ãƒˆã‚’è¿½åŠ ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</string> <string name="err_point_unknown_position">ç¾åœ¨åœ°ã‚’èªè˜ã§ãã¾ã›ã‚“。</string> - <string name="err_point_no_position_given_title">å¿…è¦ãªæƒ…å ±</string> + <string name="err_point_no_position_given_title">æƒ…å ±ãŒå¿…è¦ã§ã™</string> <string name="err_point_no_position_given">å°‘ãªãã¨ã‚‚経度ã€ç·¯åº¦ã€ã¾ãŸã¯è·é›¢ã¨æ–¹ä½ã‚’入力ã—ã¦ãã ã•ã„。全ã¦ã‚’入力ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚</string> - <string name="err_point_curr_position_unavailable">ç¾åœ¨åœ°ã®åº§æ¨™ãŒåˆ†ã‹ã‚Šã¾ã›ã‚“。もã†å°‘ã—ãŠå¾…ã¡ãã ã•ã„…</string> <string name="err_point_bear_and_dist_title">ヘルプãŒå¿…è¦?</string> <string name="err_point_bear_and_dist">æ–¹ä½ã¨è·é›¢ã‚’入力ã—ã¦ãã ã•ã„。方ä½ã¯åŒ—を基準ã¨ã—ã¦æ™‚計回りã«0~360度ã§è¡¨ã—å˜ä½ã¯ä»˜ã‘ãªã„ã§ãã ã•ã„。</string> <string name="err_log_load_data">ãƒã‚°ã‚’書ãã®ã«å¿…è¦ãªãƒ‡ãƒ¼ã‚¿ã‚’ãƒãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。</string> <string name="err_log_load_data_again">ãƒã‚°ã‚’書ãã®ã«å¿…è¦ãªãƒ‡ãƒ¼ã‚¿ã‚’ãƒãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。もã†ä¸€åº¦ã‚„ã£ã¦ã¿ã¦ãã ã•ã„。</string> <string name="err_log_load_data_still">ãƒã‚°ã‚’投稿ã™ã‚‹ã®ã«å¿…è¦ãªãƒ‡ãƒ¼ã‚¿ã‚’ã¾ã ãƒãƒ¼ãƒ‰ä¸ã§ã™ã€‚ã‚‚ã†å°‘ã—ãŠå¾…ã¡ãã ã•ã„。</string> - <string name="err_log_post_failed">ãƒã‚°ã‚’投稿ã™ã‚‹ã“ã¨ãŒã§ããªã‹ã£ãŸã‚ˆã†ã§ã™ã€‚Geocaching.comã§ç¢ºèªã—ã¦ãã ã•ã„。</string> - <string name="err_log_post_failed_ec">ãƒã‚°ã‚’投稿ã™ã‚‹ã“ã¨ãŒã§ããªã‹ã£ãŸã‚ˆã†ã§ã™ã€‚Extremcaching.comã§ç¢ºèªã—ã¦ãã ã•ã„。</string> - <string name="err_logimage_post_failed">ãƒã‚°ã®æ·»ä»˜ç”»åƒãŒã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã•ã‚Œãªã‹ã£ãŸã‚ˆã†ã§ã™ã€‚Geocaching.comã§ç¢ºèªã—ã¦ãã ã•ã„。</string> - <string name="err_search_address_forgot">c:geo forgot the address you tried to find.</string> + <string name="err_search_address_forgot">c:geoã¯ã‚ãªãŸã®æ¤œç´¢ã—ãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’忘れã¦ã—ã¾ã„ã¾ã—ãŸã€‚</string> <string name="err_parse_lat">緯度ã®è§£æžãŒã§ãã¾ã›ã‚“。</string> <string name="err_parse_lon">経度ã®è§£æžãŒã§ãã¾ã›ã‚“。</string> <string name="err_parse_dist">è·é›¢ã®è§£æžãŒã§ãã¾ã›ã‚“。</string> @@ -200,7 +194,7 @@ <string name="info_select_logimage_cancelled">添付画åƒã®ãƒ•ã‚¡ã‚¤ãƒ«é¸æŠžã¾ãŸã¯æ’®å½±ãŒã‚ャンセルã•ã‚Œã¾ã—ãŸã€‚</string> <string name="info_stored_image">æ–°è¦ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«ã®ä¿å˜å ´æ‰€:</string> <string name="info_storing_static_maps">オフライン用ã«åœ°å›³ã‚’ä¿å˜ä¸</string> - <string name="loc_last">Last known</string> + <string name="loc_last">判明ã—ãŸæœ€å¾Œã®ä½ç½®</string> <string name="loc_net">ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯</string> <string name="loc_gps">GPS</string> <string name="loc_sat">衛星</string> @@ -213,12 +207,12 @@ <string name="menu_history">å±¥æ´</string> <string name="menu_filter">フィルター</string> <string name="menu_scan_geo">QRコードスã‚ャン</string> + <string name="menu_pocket_queries">ãƒã‚±ãƒƒãƒˆãƒ»ã‚¯ã‚¨ãƒª</string> <string name="menu_scan_description">QRコードã«ã—ãŸGCコードをスã‚ャンã§ãã¾ã™ãŒå¿…è¦ãªã‚¢ãƒ—リãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。Google Playã‹ã‚‰ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã‹?</string> <string name="live_map_button">地図</string> <string name="caches_nearby_button">è¿‘ã</string> <string name="advanced_search_button">検索</string> <string name="stored_caches_button">ä¿å˜æ¸ˆã¿</string> - <string name="any_button">目的地</string> <string name="unknown_scan">GCコードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</string> <string name="caches_no_cache">ã‚ャッシュã¯ã‚ã‚Šã¾ã›ã‚“</string> <string name="caches_more_caches">次ã®ã‚ャッシュ</string> @@ -239,12 +233,12 @@ <string name="caches_sort_difficulty">難易度</string> <string name="caches_sort_terrain">地形</string> <string name="caches_sort_size">サイズ</string> - <string name="caches_sort_favorites">人気</string> + <string name="caches_sort_favorites">ãŠæ°—ã«å…¥ã‚Š</string> <string name="caches_sort_favorites_ratio">ãŠæ°—ã«å…¥ã‚Š [%]</string> <string name="caches_sort_name">åå‰</string> <string name="caches_sort_geocode">GCコード</string> <string name="caches_sort_rating">評価</string> - <string name="caches_sort_vote">Vote (Own Rating)</string> + <string name="caches_sort_vote">自己評価</string> <string name="caches_sort_inventory">目録ã®æ•°</string> <string name="caches_sort_date_hidden">è¨ç½®æ—¥</string> <string name="caches_sort_date_logged">ãƒã‚°ãŒæ›¸ã‹ã‚ŒãŸæ—¥</string> @@ -256,6 +250,7 @@ <string name="caches_select_invert">é¸æŠžã‚’å転</string> <string name="caches_nearby">ç¾åœ¨åœ°ã®è¿‘ã</string> <string name="caches_manage">管ç†</string> + <string name="caches_remove_progress">ã‚ャッシュを削除ä¸</string> <string name="caches_delete_events">éŽåŽ»ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’削除</string> <string name="caches_refresh_selected">é¸æŠžã—ãŸã‚ャッシュを更新</string> <string name="caches_refresh_all">å…¨ã¦ã®ã‚ャッシュを更新</string> @@ -274,7 +269,7 @@ <string name="caches_filter_track">トラッカブルã‚ã‚Š</string> <string name="caches_filter_clear">フィルターをクリア</string> <string name="caches_filter_modified">座標ã®æ›´æ–°ã‚ã‚Š</string> - <string name="caches_filter_origin">Origin</string> + <string name="caches_filter_origin">原点</string> <string name="caches_filter_distance">è·é›¢</string> <string name="caches_filter_personal_note">パーソナルノート付ã</string> <string name="caches_filter_popularity">ãŠæ°—ã«å…¥ã‚Š</string> @@ -561,7 +556,6 @@ <string name="cache_menu_streetview">Googleストリートビュー</string> <string name="cache_menu_browser">ブラウザã§é–‹ã</string> <string name="cache_menu_visit">ãƒã‚°ã‚’書ã</string> - <string name="cache_menu_visit_offline">ãƒã‚°ã‚’書ã(オフライン)</string> <string name="cache_menu_spoilers">スãƒã‚¤ãƒ©ãƒ¼ç”»åƒ</string> <string name="cache_menu_around">è¿‘ãã®ã‚ャッシュ</string> <string name="cache_menu_event">カレンダーã«ç™»éŒ²</string> @@ -777,7 +771,6 @@ <string name="helper_contacts_title">c:geo - 連絡先アドオン</string> <string name="helper_sendtocgeo_description">Send to c:geoã¯<strong>PC用</strong>ブラウザã®æ‹¡å¼µæ©Ÿèƒ½ã§ã™ã€‚PCã®ãƒ–ラウザã§è¡¨ç¤ºã—ã¦ã‚‹ã‚ãƒ£ãƒƒã‚·ãƒ¥æƒ…å ±ã‚’ã‚¢ãƒ³ãƒ‰ãƒã‚¤ãƒ‰ç«¯æœ«ã«ç›´æŽ¥é€ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">シンプルã§å½¹ã«ç«‹ã¤åœ°å›³ã‚¢ãƒ—リ。オフライン用ã«åœ°å›³ã‚’直接ダウンãƒãƒ¼ãƒ‰(ç”»åƒãƒ‡ãƒ¼ã‚¿ã®ã¿)ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚軌跡(GPSãƒã‚°)を記録ã—ãŸã‚Šã€POIを扱ã£ãŸã‚Šã€ãã®ä»–ã‚‚ãŸãã•ã‚“便利ãªæ©Ÿèƒ½ãŒã‚ã‚Šã¾ã™ã€‚</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">c:geoã§ã“ã®ã‚¢ãƒ—リã®ãƒ¬ãƒ¼ãƒ€ãƒ¼ã‚’利用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®ä»–ã€GPSã«é–¢ã™ã‚‹ãŸãã•ã‚“ã®æƒ…å ±ãŒå¾—られã¾ã™ã€‚</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -998,11 +991,6 @@ Google翻訳アプリã§å„言語ã®è¾žæ›¸ã‚’ダウンãƒãƒ¼ãƒ‰ã—ã¦ãŠã‘ã°ã‚ <string name="attribute_geotour_no">ジオツアーã®ä¸€éƒ¨ã§ã¯ãªã„</string> <string name="quote">To make geocaching easier, to make users lazier.</string> <string name="powered_by">carnero</string> - <string name="support">サãƒãƒ¼ãƒˆ: <a href="">support@cgeo.org</a></string> - <string name="website">Webサイト: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">Google Playã®c:geo</a></string> <string name="about_twitter">ã‚ャッシュã®ãƒã‚°ã‚’書ã„ãŸã‚‰<b>c:geo</b>ã«Twitterã§ã¤ã¶ã‚„ã„ã¦ã»ã—ã„?</string> <string name="status_new_release" tools:ignore="UnusedResources">æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã™ã€‚\nクリックã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。</string> <string name="status_new_nightly" tools:ignore="UnusedResources">æ–°ã—ã„ナイトリービルドãŒã‚ã‚Šã¾ã™ã€‚\nクリックã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。</string> diff --git a/main/res/values-lt/strings.xml b/main/res/values-lt/strings.xml index d0e6f9d..f20a913 100644 --- a/main/res/values-lt/strings.xml +++ b/main/res/values-lt/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">ApsilankÄ—</string> <string name="log_tb_drop">Paliktas</string> <string name="log_tb_changeall">Keisti visus</string> - <string name="log_save">IÅ¡saugoti</string> + <string name="log_save">IÅ¡saugoti neprisijungus</string> <string name="log_saving">SiunÄiamas įraÅ¡as…</string> <string name="log_saving_and_uploading">SiunÄiamas įraÅ¡as ir įkeliama nuotrauka…</string> <string name="log_clear">IÅ¡valyti</string> <string name="log_post_not_possible">Ä®keliamas įraÅ¡o puslapis…</string> + <string name="log_date_future_not_allowed">BÅ«simos datos įraÅ¡ai negalimi.</string> <string name="log_add">PridÄ—ti</string> + <string name="log_repeat">Pakartoti paskutinį įraÅ¡Ä…</string> <string name="log_no_rating">NÄ—ra reitingo</string> <string name="log_stars_1_description">Prasta</string> <string name="log_stars_15_description">Pakankamai prasta</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Ä®raÅ¡o slaptažodis:</string> <string name="log_hint_log_password">Ä®veskite savo įraÅ¡o slaptažodį</string> <string name="log_oc_team_comment">OC komandos komentaras</string> + <string name="log_your_saved_log">JÅ«sų iÅ¡saugotas įraÅ¡as</string> <string-array name="log_image_scales"> <item>Nekeisti dydžio</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">NÄ—ra iÅ¡saugotos prisijungimo informacijos</string> <string name="err_login_failed_toast">c:geo negali prisijungti. c:geo veikia neprisijungusi su iÅ¡saugotomis slÄ—ptuvÄ—mis. Patikrinkite prisijungimo nustatymus arba įjunkite prietaiso interneto ryšį.</string> <string name="err_unknown">Nežinoma klaida</string> + <string name="err_unknown_address">C:geo nepavyko susieti Å¡io adreso su egzistuojanÄia vietove</string> <string name="err_comm">Nežinoma ryÅ¡io klaida</string> <string name="err_missing_auth">Neįvestas vartotojo vardas ir/ar slaptažodis.</string> <string name="err_wrong">Neteisinga prisijungimo informacija</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Nepavyko pasiekti nuotraukos.</string> <string name="err_tb_display">c:geo negali parodyti norimo keliauninko. Ar tai tikrai keliauninkas?</string> <string name="err_tb_details_open">c:geo negali atidaryti keliauninko informacijos.</string> - <string name="err_tb_forgot_saw">c:geo pamirÅ¡o kokį keliauninkÄ… žiÅ«rÄ—jote.</string> <string name="err_tb_find">c:geo neranda keliauninko</string> <string name="err_tb_find_that">c:geo neranda Å¡ito keliauninko.</string> <string name="err_waypoint_cache_unknown">c:geo nežino, kokiai slÄ—ptuvei norite pridÄ—ti papildomÄ… taÅ¡kÄ….</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo neranda JÅ«sų buvimo vietos.</string> <string name="err_point_no_position_given_title">Reikalinga informacija</string> <string name="err_point_no_position_given">Užpildykite bent platumÄ… ir ilgumÄ… arba atstumÄ… ir azimutÄ…. Taip pat galite užpildyt ir visus keturis laukelius.</string> - <string name="err_point_curr_position_unavailable">c:geo dar negavo vietos koordinaÄių. PraÅ¡ome palaukti…</string> <string name="err_point_bear_and_dist_title">Reikalinga pagalba?</string> <string name="err_point_bear_and_dist">Užpildykite azimutÄ… ir atstumÄ…. Azimutas tai nuo 0 iki 360 laipsnių kampas nuo Å¡iaurÄ—s. Atstumas nereikalauja matavimo vienetų.</string> <string name="err_log_load_data">c:geo negali įkelti duomenų reikalingų apsilankymui įraÅ¡yti.</string> <string name="err_log_load_data_again">c:geo negali įkelti duomenų reikalingų apsilankymui įraÅ¡yti. Bando dar kartÄ….</string> <string name="err_log_load_data_still">c:geo dar įkelia duomenis reikalingus apsilankymui įraÅ¡yti. PraÅ¡ome palaukti Å¡iek tiek ilgiau.</string> - <string name="err_log_post_failed">Atrodo, kad jÅ«sų įraÅ¡as nebuvo paskelbtas. PraÅ¡ome tai patikrinti Geocaching.com.</string> - <string name="err_log_post_failed_ec">Atrodo, kad jÅ«sų įraÅ¡as nebuvo paskelbtas. PraÅ¡ome tai patikrinti Extremcaching.com.</string> - <string name="err_logimage_post_failed">Atrodo, kad jÅ«sų įraÅ¡o nuotrauka nebuvo įkelta. PraÅ¡ome tai patikrinti Geocaching.com.</string> + <string name="err_log_post_failed">Atrodo, kad jÅ«sų įraÅ¡as nebuvo paskelbtas. PraÅ¡ome patikrinti jį slÄ—ptuvÄ—s svetainÄ—je.</string> + <string name="err_logimage_post_failed">Atrodo, kad jÅ«sų įraÅ¡o nuotrauka nebuvo paskelbta. PraÅ¡ome patikrinti jÄ… slÄ—ptuvÄ—s svetainÄ—je.</string> <string name="err_search_address_forgot">c:geo pamirÅ¡o adresÄ… kurio bandÄ—te ieÅ¡koti.</string> <string name="err_parse_lat">c:geo nesupranta įvestos platumos.</string> <string name="err_parse_lon">c:geo nesupranta įvestos ilgumos.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Tinklas</string> <string name="loc_fused">Sujungta</string> <string name="loc_low_power">Energijos taupymas</string> + <string name="loc_home">Namų koordinatÄ—s</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Pal.</string> <string name="loc_trying">Bandoma nustatyti</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Netoliese</string> <string name="advanced_search_button">IeÅ¡koti</string> <string name="stored_caches_button">IÅ¡saugota</string> - <string name="any_button">Bet kur</string> + <string name="any_button">Eiti į</string> <string name="unknown_scan">Nepavyko rasti geo kodo.</string> <string name="caches_no_cache">SlÄ—ptuvių Äia nÄ—ra</string> <string name="caches_more_caches">Ä®kelti daugiau slÄ—ptuvių</string> @@ -264,15 +266,24 @@ <string name="caches_sort_finds">Radimų kiekis</string> <string name="caches_sort_state">BÅ«sena</string> <string name="caches_sort_storage">IÅ¡saugojimo prietaise data</string> + <string name="caches_sort_eventdate">Renginio data</string> <string name="caches_select_mode">Pasirinkti</string> <string name="caches_select_mode_exit">Nebesirinkti</string> <string name="caches_select_invert">ŽymÄ—ti prieÅ¡ingai</string> <string name="caches_nearby">Netoliese</string> <string name="caches_manage">Valdyti</string> <string name="caches_remove_all">PaÅ¡alinti visas</string> - <string name="caches_remove_all_confirm">Ar norite paÅ¡alinti visas %s slÄ—ptuves iÅ¡ dabartinio sÄ…raÅ¡o?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Ar norite paÅ¡alinti slÄ—ptuvÄ™ iÅ¡ dabartinio sÄ…raÅ¡o?</item> + <item quantity="few">Ar norite paÅ¡alinti visas %d slÄ—ptuves iÅ¡ dabartinio sÄ…raÅ¡o?</item> + <item quantity="other">Ar norite paÅ¡alinti visas %d slÄ—ptuvių iÅ¡ dabartinio sÄ…raÅ¡o?</item> + </plurals> <string name="caches_remove_selected">PaÅ¡alinti pasirinktÄ…</string> - <string name="caches_remove_selected_confirm">Ar norite paÅ¡alinti pasirinktas %s slÄ—ptuves iÅ¡ prietaiso?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Ar norite paÅ¡alinti slÄ—ptuvÄ™ iÅ¡ prietaiso?</item> + <item quantity="few">Ar norite paÅ¡alinti pasirinktas %d slÄ—ptuves iÅ¡ prietaiso?</item> + <item quantity="other">Ar norite paÅ¡alinti pasirinktas %d slÄ—ptuvių iÅ¡ prietaiso?</item> + </plurals> <string name="caches_remove_progress">PaÅ¡alinamos slÄ—ptuvÄ—s</string> <string name="caches_delete_events">IÅ¡trinti praeities įvykius</string> <string name="caches_refresh_selected">Atnaujinti pasirinktas</string> @@ -292,13 +303,18 @@ <string name="caches_filter_track">Su keliauninkais</string> <string name="caches_filter_clear">Valyti filtrus</string> <string name="caches_filter_modified">Su pakeistomis koordinatÄ—mis</string> + <string name="caches_filter_offline_log">Su iÅ¡saugotu įraÅ¡u</string> <string name="caches_filter_origin">Å altinis</string> <string name="caches_filter_distance">Atstumas</string> <string name="caches_filter_personal_note">Su asmenine pastaba</string> <string name="caches_filter_popularity">Kaip mÄ—giamos</string> <string name="caches_filter_popularity_ratio">Kaip mÄ—giamos [%]</string> + <string name="caches_filter_personal_data">Su asmeniniais duomenimis</string> + <string name="caches_filter_rating">Su reitingu</string> + <string name="caches_filter_own_rating">Su savo reitingu</string> <string name="caches_removing_from_history">PaÅ¡alinama iÅ¡ Istorijos…</string> <string name="caches_clear_offlinelogs">IÅ¡valyti iÅ¡saugotus įraÅ¡us</string> + <string name="caches_clear_offlinelogs_message">Ar norite iÅ¡valyti iÅ¡saugotus įraÅ¡us?</string> <string name="caches_clear_offlinelogs_progress">IÅ¡valomi iÅ¡saugoti įraÅ¡ai</string> <string name="list_menu_create">Sukurti naujÄ… sÄ…raÅ¡Ä…</string> <string name="list_menu_drop">IÅ¡mesti dabartinį sÄ…raÅ¡Ä…</string> @@ -321,13 +337,17 @@ <string name="list_not_available">SÄ…raÅ¡as nebeprieinamas, pereinama į standartinį sÄ…raÅ¡Ä…</string> <string name="about_version">Versija</string> <string name="about_changelog">Pakeitimų žurnalas</string> + <string name="about_system">Sistema</string> <string name="about_donate">Paaukoti</string> <string name="about_donation_more">Paaukoti\nkÅ«rÄ—jams</string> <string name="about_contributors">Bendraautoriai</string> <string name="about_license">Licencija</string> <string name="about_apache_license"><a href=""> Apache licencija, versija 2.0</a></string> <string name="about_help">Pagalba</string> + <string name="about_system_include">PridÄ—kite papildomÄ… sisteminÄ™ informacijÄ…, kai siunÄiate klaidos praneÅ¡imÄ… arba norite gauti daugiau informacijos apie c:geo:</string> + <string name="changelog_github">Pakeitimų sÄ…raÅ¡as</string> <string name="settings_title_services">Paslaugos</string> + <string name="settings_summary_services">Nustatyk naudotojo paskyros informacijÄ… ir prieiga prie pasirinktinų paslaugų.</string> <string name="settings_title_appearance">IÅ¡vaizda</string> <string name="settings_title_cachedetails">SlÄ—ptuvÄ—s informacija</string> <string name="settings_title_offlinedata">Duomenys darbui neprisijungus</string> @@ -365,6 +385,9 @@ <string name="settings_activate_oc_uk">Aktyvuoti</string> <string name="init_oc_uk_description">Leiskite c:geo prisijungti prie opencaching.org.uk tam, kad galÄ—tumÄ—t ieÅ¡koti slÄ—ptuvių ir pasiekti/filtruoti rastas slÄ—ptuves.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Kad bÅ«tų galima reitinguoti slÄ—ptuvÄ™, sekite instrukcijÄ… GCVote.com svetainÄ—je ir Äia įveskite GCVote slaptažodį.</string> + <string name="err_gcvote_send_rating">Klaida siunÄiant reitingÄ…, patikrinkite GCVote slaptažodį parametruose arba jį iÅ¡trinkite.</string> + <string name="gcvote_sent">Balsas sÄ—kmingai iÅ¡siųstas</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktyvuoti</string> <string name="init_username">Vartotojo vardas</string> @@ -435,6 +458,8 @@ <string name="init_backup_success">c:geo duomenų bazÄ— sÄ—kmingai nukopijuota į:</string> <string name="init_backup_failed">Nepavyko sukurti atsarginÄ—s c:geo duomenų bazÄ—s kopijos.</string> <string name="init_backup_unnecessary">Duomenų bazÄ— tuÅ¡Äia, atsarginÄ— kopija nereikalinga.</string> + <string name="backup_confirm_overwrite">Ar norite perraÅ¡yti esamÄ… atsarginÄ™ kopijÄ… nuo %s?</string> + <string name="restore_confirm_overwrite">Ar norite perraÅ¡yti %s įrenginyje su atsargine kopija?</string> <string name="init_restore_success">AtkÅ«rimas baigtas.</string> <string name="init_restore_failed">Atkurti nepavyko.</string> <string name="init_restore_running">Atkuriama slÄ—ptuvių duomenų bazė…</string> @@ -593,6 +618,7 @@ </plurals> <string name="cache_waypoints_add">PridÄ—ti papildomÄ… taÅ¡kÄ…</string> <string name="cache_hint">Užuomina</string> + <string name="cache_hint_not_available">Užuomina nepateikiama</string> <string name="cache_logs">Ä®raÅ¡ai</string> <string name="cache_logs_friends_and_own">Draugų/savi įraÅ¡ai</string> <string name="cache_dialog_loading_details">Ä®keliama slÄ—ptuvÄ—s informacija…</string> @@ -632,9 +658,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Atidaryti narÅ¡yklÄ—je</string> <string name="cache_menu_visit">Registruoti</string> - <string name="cache_menu_visit_offline">Registruoti neprisijungus</string> + <string name="cache_menu_visit_offline">Vienu paspaudimu žurnalo įraÅ¡o iÅ¡saugojimas</string> <string name="cache_menu_spoilers">Užuominų nuotraukos</string> <string name="cache_menu_around">SlÄ—ptuvÄ—s aplink</string> + <string name="around">Aplink %s</string> <string name="cache_menu_event">Ä®traukti į kalendorių</string> <string name="cache_menu_details">Informacija</string> <string name="cache_menu_refresh">Atnaujinti</string> @@ -643,6 +670,8 @@ <string name="cache_menu_whereyougo">WhereYouGo</string> <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Balsuoti</string> + <string name="cache_menu_ignore">Ignoruoti slÄ—ptuvÄ™</string> <string name="cache_status">BÅ«sena</string> <string name="cache_status_offline_log">IÅ¡saugotas įraÅ¡as</string> <string name="cache_status_found">Rasta</string> @@ -752,6 +781,8 @@ <string name="search_clear_history">IÅ¡valyti istorijÄ…</string> <string name="search_history_cleared">Istorija iÅ¡valyta</string> <string name="waypoint_coordinate_formats_plain">Paprastas</string> + <string name="from_clipboard">IÅ¡ mainų srities</string> + <string name="copy_to_clipboard">Kopijuoti į mainų sritį</string> <string name="visit_tweet">Skelbti radybas Twitter paskytoje</string> <string name="map_map">IÅ¡saugotos slÄ—ptuvÄ—s</string> <string name="map_live">SlÄ—ptuvÄ—s iÅ¡ interneto</string> @@ -856,7 +887,7 @@ <string name="helper_contacts_description">Leidžia tiesiai iÅ¡ įraÅ¡o atidaryti kontakto kortelÄ™ (iÅ¡ jÅ«sų adresų knygos), kad galÄ—tumÄ—te susisiekti su draugais papraÅ¡yti pagalbos.</string> <string name="helper_sendtocgeo_description">Send to c:geo yra <strong>jÅ«sų kompiuterio</strong> narÅ¡yklÄ—s priedas . Kai narÅ¡ote geocaching.com, jÅ«s galite siųsti slÄ—ptuves į savo iÅ¡manųjį telefonÄ… tiesiog narÅ¡yklÄ—s viduje paspausdami mygtukÄ….</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Patogi programa, kuri rodo žemÄ—lapius tiesiai iÅ¡ interneto ir suteikia galimybÄ™ atsisiųsti juos į prietaisÄ… (tik rastrinius žemÄ—lapius). Ji taip pat palaiko nukeliauto kelio įraÅ¡ymÄ…, lankytinų vietų valdymÄ… ir turi daug kitų naudingų funkcijų.</string> + <string name="helper_locus_description">Navigacijos programa JÅ«sų telefonui. ŽiÅ«rÄ—kite iÅ¡saugotus topo žemÄ—lapius, įraÅ¡ykite savo marÅ¡rutÄ…, ieÅ¡kokite slÄ—ptuves, naudokite balso komandas ir dar daugiau.</string> <string name="helper_gpsstatus_title">GPS Status & Toolbox</string> <string name="helper_gpsstatus_description">Kartu su c:geo galite naudoti Å¡ioje programoje esantį radarÄ…. Ji taip pat siÅ«lo daug kitos su GPS susijusios informacijos.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1107,12 +1138,15 @@ <string name="attribute_offset_cache_yes">Offset cache</string> <string name="attribute_offset_cache_no">No offset cache</string> <string name="quote">To make geocaching easier, to make users lazier.</string> - <string name="support">Palaikymas: <a href="">support@cgeo.org</a></string> - <string name="website">Tinklapis: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo on Google Play</a></string> + <string name="support_title">Palaikymas</string> + <string name="website_title">Tinklapis</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href=""> c:Geo puslapis</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo Google Play</a></string> <string name="about_twitter">Kaskart registruojant slÄ—ptuvÄ™ <b>c:geo</b> paskelbs nauja statusÄ… Twitter paskyroje.</string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Galima nauja versija. \nPaspauskite Äia ir įdiekite.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Galima nauja naktinÄ— versija.\nPaspauskite Äia ir įdiekite.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Galima nauja versija. \nPaspauskite Äia ir įdiekite.</string> @@ -1163,7 +1197,7 @@ <item quantity="few">%s mÄ—giamos</item> <item quantity="other">%s mÄ—giamų</item> </plurals> - <string name="percent_favorite_points">%\ mÄ—giamos</string> + <string name="more_than_percent_favorite_points">> %d%% megstami</string> <string name="cgeo_shortcut">c:geo nuoroda</string> <string name="create_shortcut">Sukurti nuorodÄ…</string> <string name="send">Siųsti</string> diff --git a/main/res/values-lv/strings.xml b/main/res/values-lv/strings.xml new file mode 100644 index 0000000..3a23710 --- /dev/null +++ b/main/res/values-lv/strings.xml @@ -0,0 +1,773 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources xmlns:tools="http://schemas.android.com/tools"> + <string name="app_name">c:geo</string> + <string name="cache">SlÄ“pnis</string> + <string name="detail">InformÄcija</string> + <string name="search">MeklÄ“Å¡ana</string> + <string name="helpers">NoderÄ«gas aplikÄcijas</string> + <string name="about">Par c:geo</string> + <string name="latitude">Platums</string> + <string name="longitude">Garums</string> + <string name="settings_titlebar">c:geo iestatÄ«jumi</string> + <string name="all_types">Visi slÄ“pņu veidi</string> + <string name="traditional">TradicionÄlais slÄ“pnis</string> + <string name="multi">MultislÄ“pnis</string> + <string name="mystery">MistÄ“rijas/mÄ«klas slÄ“pnis</string> + <string name="letterbox">Letterbox hibrÄ«ds</string> + <string name="event">Event slÄ“pnis</string> + <string name="mega">Mega-Event slÄ“pnis</string> + <string name="giga">Giga-Event slÄ“pnis</string> + <string name="earth">Zemes slÄ“pnis</string> + <string name="cito">Cache In Trash Out pasÄkums (CITO)</string> + <string name="webcam">TÄ«mekļa kameras slÄ“pnis</string> + <string name="virtual">VirtuÄlais slÄ“pnis</string> + <string name="wherigo">Wherigo slÄ“pnis</string> + <string name="lostfound">Lost & Found PasÄkuma slÄ“pnis</string> + <string name="ape">Projekta A.P.E. slÄ“pnis</string> + <string name="gchq">Groundspeak HQ</string> + <string name="gps">GPS Adventures Exhibit</string> + <string name="block">Groundspeak Block Party</string> + <string name="unknown">NezinÄms tips</string> + <string name="cache_size_micro">Mikro</string> + <string name="cache_size_small">Mazs</string> + <string name="cache_size_regular">Parasts</string> + <string name="cache_size_large">Liels</string> + <string name="cache_size_other">Cits</string> + <string name="cache_size_virtual">VirtuÄls</string> + <string name="cache_size_notchosen">Nav izvÄ“lÄ“ts</string> + <string name="cache_size_unknown">NezinÄms</string> + <string name="cache_size_nano">Nano</string> + <string name="cache_size_very_large">Ä»oti liels</string> + <string name="wp_final">FinÄla vieta</string> + <string name="wp_stage">MultislÄ“pņa posms</string> + <string name="wp_puzzle">JautÄjums, kas prasa atbildi</string> + <string name="wp_pkg">StÄvvieta</string> + <string name="wp_trailhead">Takas sÄkumvieta</string> + <string name="wp_waypoint">Izziņas vieta</string> + <string name="wp_original">SÄkotnÄ“jÄs koordinÄtas</string> + <string name="log_found">Atrasts</string> + <string name="log_dnf">Nav atrasts</string> + <string name="log_note">RakstÄ«t piezÄ«mi</string> + <string name="log_published">PublicÄ“ts</string> + <string name="log_enabled">IespÄ“jots</string> + <string name="log_disabled">AtspÄ“jots</string> + <string name="log_attend">PiedalÄ«Å¡os</string> + <string name="log_attended">PiedalÄ«jos</string> + <string name="log_retrieved">IegÅ«ts</string> + <string name="log_placed">Novietots</string> + <string name="log_grabbed">Paņemts kaut kur citur</string> + <string name="log_movecollection">Pievienots kolekcijai</string> + <string name="log_moveinventory">Pievienots inventÄriem</string> + <string name="log_maintained">Apkope veikta</string> + <string name="log_maintenance_needed">NepiecieÅ¡ama apkope</string> + <string name="log_update">AtjauninÄtas koordinÄtas</string> + <string name="log_archived">ArhivÄ“ts</string> + <string name="log_unarchived">AtarhivÄ“ts</string> + <string name="log_needs_archived">NepiecieÅ¡ams arhivÄ“t</string> + <string name="log_discovered">AtklÄts</string> + <string name="log_reviewer">PÄrskatÄ«tÄja piezÄ«me</string> + <string name="log_submit_for_review">Iesniegt izskatÄ«Å¡anai</string> + <string name="log_retractlisting">Aizliegto sarakstÄ</string> + <string name="log_marked_missing">AtzÄ«mÄ“ts kÄ pazudis</string> + <string name="log_tb_nothing">NedarÄ«t neko</string> + <string name="log_tb_visit">ApmeklÄ“ja</string> + <string name="log_tb_drop">Nometa</string> + <string name="log_tb_changeall">MainÄ«t visus</string> + <string name="log_save">SaglabÄt bezsaistes režīmÄ</string> + <string name="log_saving">ApmeklÄ“juma ieraksta nosÅ«tÄ«Å¡ana…</string> + <string name="log_saving_and_uploading">Pieraksta nosÅ«tÄ«Å¡ana un bildes augÅ¡upielÄde…</string> + <string name="log_clear">NotÄ«rÄ«t</string> + <string name="log_post_not_possible">IelÄdÄ“ apmeklÄ“juma ierasta lapu…</string> + <string name="log_add">Pievienot</string> + <string name="log_repeat">AtkÄrtot iepriekÅ¡Ä“jo reÄ£istrÄ“Å¡anos</string> + <string name="log_no_rating">Nav vÄ“rtÄ“juma</string> + <string name="log_stars_1_description">Slikti</string> + <string name="log_stars_15_description">Diezgan slikti</string> + <string name="log_stars_2_description">Zem vidÄ“jÄ</string> + <string name="log_stars_25_description">Nav slikti</string> + <string name="log_stars_3_description">VidÄ“ji</string> + <string name="log_stars_35_description">VispÄr nav slikti</string> + <string name="log_stars_4_description">LabÄk nekÄ vidÄ“ji</string> + <string name="log_stars_45_description">Ä»oti labi</string> + <string name="log_stars_5_description">VienreizÄ“ji</string> + <string name="log_webcam">TÄ«mekļa kameras fotogrÄfija uzņemta</string> + <string name="log_new_log">ReÄ£istrÄ“t apmeklÄ“jumu</string> + <string name="log_new_log_text">ApmeklÄ“juma teksts</string> + <string name="log_announcement">Paziņojums</string> + <string name="log_today">Å odien</string> + <string name="log_yesterday">Vakar</string> + <string name="log_smilies">Smaidiņi</string> + <string name="log_image">AttÄ“ls</string> + <string name="log_image_attach">Pievienot attÄ“lu</string> + <string name="log_image_stored">EsoÅ¡o</string> + <string name="log_image_camera">Jaunu</string> + <string name="log_image_caption">Nosaukums</string> + <string name="log_image_description">Apraksts</string> + <string name="log_image_scale">MÄ“rogoÅ¡ana</string> + <string name="log_password_title">PierakstÄ«Å¡anÄs parole:</string> + <string name="log_hint_log_password">Ievadiet savu pierakstÄ«Å¡anÄs paroli</string> + <string name="log_oc_team_comment">OC Team komentÄrs</string> + <string-array name="log_image_scales"> + <item>Bez mÄ“rogoÅ¡anas</item> + <item>512 px</item> + <item>640 px</item> + <item>800 px</item> + <item>1024 px</item> + </string-array> + <string name="translate_to_sys_lang">Tulkot uz %s valodu</string> + <string name="translate_to_english">Tulkot uz angļu valodu</string> + <string name="translate_length_warning">Tulkojums var neizdoties liela teksta apjoma dēļ.</string> + <string name="err_none">OK</string> + <string name="err_parse">Kļūda autorizÄcijas lapas apstrÄdÄ“</string> + <string name="err_server">Nevar sazinÄties ar Geocaching.com. Vietne Å¡obrÄ«d var nedarboties vai arÄ« jÅ«su interneta savienojums nedarbojas.</string> + <string name="err_server_ec">Nevar sazinÄties ar Extremcaching.com. Vietne Å¡obrÄ«d var nedarboties vai arÄ« jÅ«su interneta savienojums nedarbojas.</string> + <string name="err_login">Nav saglabÄta pieteikÅ¡anÄs informÄcija</string> + <string name="err_login_failed_toast">c:geo nevar pierakstÄ«ties. c:geo darbojas bezsaistÄ“ ar bezsaistÄ“ saglabÄtajiem slÄ“pņiem. PÄrbaudiet ielogoÅ¡anÄs iestatÄ«jumus vai iespÄ“jojiet interneta savienojumu.</string> + <string name="err_unknown">NezinÄma kļūda</string> + <string name="err_unknown_address">c:geo nevarÄ“ja atrast kartÄ“ Å¡o adresi ar paÅ¡reizÄ“jo atraÅ¡anÄs vietu</string> + <string name="err_comm">NezinÄma sakaru kļūda</string> + <string name="err_missing_auth">Nav uzstÄdÄ«ts lietotÄjvÄrds un/vai parole.</string> + <string name="err_wrong">PieteikÅ¡anÄs informÄcija ir nepareiza</string> + <string name="err_maintenance">Geocaching.com apkopes dēļ nedarbojas. c:geo strÄdÄ bezsaistÄ“ ar saglabÄtajiem bezsaistÄ“ slÄ“pņiem.</string> + <string name="err_license">JÅ«s neesat piekritis Geocaching.com licences lÄ«gumam, tÄpÄ“c c:geo nevar ielÄdÄ“t slÄ“pņu koordinÄtas.</string> + <string name="err_unvalidated_account">Vispirms Jums jÄapstiprina savs konts vietnÄ“ Geocaching.com.</string> + <string name="err_unpublished">PieprasÄ«tais slÄ“pnis nav publicÄ“ts.</string> + <string name="err_premium_only">Å Ä«s slÄ“pnis ir pieejams tikai Geocaching.com Premium lietotÄjiem.</string> + <string name="err_detail_open">c:geo nevar atvÄ“rt Ä£eoslÄ“pņa informÄciju.</string> + <string name="err_detail_cache">c:geo nevar parÄdÄ«t izvÄ“lÄ“to Ä£eoslÄ“pni. Tas tieÅ¡Äm ir Ä£eoslÄ“pnis?</string> + <string name="err_detail_cache_find">c:geo nevar atrast Ä£eoslÄ“pni</string> + <string name="err_detail_cache_find_some">c:geo nevar atrast Å¡o Ä£eoslÄ“pni.</string> + <string name="err_detail_cache_find_any">c:geo nevar atrast nevienu Ä£eoslÄ“pni.</string> + <string name="err_detail_google_maps_limit_reached">c:geo neizdevÄs lejupielÄdÄ“t statiskÄs kartes. VarbÅ«t Google Maps API limits ir pÄrsniegts.</string> + <string name="err_detail_no_spoiler">c:geo neatrada spoilerbildi Å¡im slÄ“pnim.</string> + <string name="err_detail_no_map_static">c:geo neatrod statiskÄs kartes Å¡im slÄ“pnim.</string> + <string name="err_detail_not_load_map_static">c:geo neizdevÄs ielÄdÄ“t statiskÄs kartes.</string> + <string name="err_detail_still_working">JoprojÄm strÄdÄ pie citas darbÄ«bas.</string> + <string name="err_watchlist_still_managing">JoprojÄm kÄrto tavu novÄ“rojamo slÄ“pņu sarakstu.</string> + <string name="err_watchlist_failed">NeizdevÄs mainÄ«t tavu novÄ“rojamo slÄ“pņu sarakstu.</string> + <string name="err_application_no">c:geo nevar atrast nevienu piemÄ“rotu aplikÄciju.</string> + <string name="err_auth_initialize">c:geo neizdevÄs izpildÄ«t pierakstÄ«Å¡anÄs procesu.</string> + <string name="err_auth_process">PierakstÄ«Å¡anÄs process neizdevÄs.</string> + <string name="err_cannot_log_visit">c:geo nevar pierakstÄ«t jÅ«su apmeklÄ“jumu. LÅ«dzu, pierakstiet savu apmeklÄ“jumu no pilna slÄ“pņa apraksta loga.</string> + <string name="err_download_fail">c:geo neizdevÄs lejupielÄdÄ“t slÄ“pņus.</string> + <string name="err_dwld_details_failed">c:geo neizdevÄs lejupielÄdÄ“t slÄ“pņa datus.</string> + <string name="err_load_descr_failed">c:geo nevar ielÄdÄ“t aprakstu.</string> + <string name="err_location_unknown">c:geo nezina slÄ“pņa atraÅ¡anÄs vietu.</string> + <string name="err_missing_device_name">LÅ«dzu, ievadiet ierÄ«ces nosaukumu pirms reÄ£istrÄ“Å¡anÄs.</string> + <string name="err_favorite_failed">FavorÄ«ta statusa maiņa neizdevÄs.</string> + <string name="err_select_logimage_failed">AttÄ“lu atlasÄ«Å¡ana priekÅ¡ pierakstÄ«Å¡anÄs neizdevÄs.</string> + <string name="err_acquire_image_failed">AttÄ“la iegÅ«Å¡ana neizdevÄs.</string> + <string name="err_tb_display">c:geo nevar parÄdÄ«t ceļotÄjums, kurus izvÄ“lÄ“jÄties. Vai tie patieÅ¡Äm ir ceļotÄji?</string> + <string name="err_tb_details_open">c:geo nevar atvÄ“rt ceļotÄja datus.</string> + <string name="err_tb_find">c:geo nevar atrast ceļotÄju</string> + <string name="err_tb_find_that">c:feo nevar atrast Å¡o ceļotÄju.</string> + <string name="err_waypoint_cache_unknown">c:geo, nezina, kuram slÄ“pnim JÅ«s vÄ“laties pievienot Starpposma punktu.</string> + <string name="err_waypoint_add_failed">c:geo neizdevÄs pievienot jÅ«su Starpposmu.</string> + <string name="err_point_unknown_position">c:geo nevar parÄdÄ«t, kur jÅ«s atrodaties.</string> + <string name="err_point_no_position_given_title">InformÄcija nepiecieÅ¡ama</string> + <string name="err_point_no_position_given">Aizpildiet vismaz platumu un garumu var arÄ« attÄlumu ar pagrieziena leņķi. Varat norÄdÄ«t visas Äetras Å¡Å«nas.</string> + <string name="err_point_bear_and_dist_title">NepiecieÅ¡ama palÄ«dzÄ«ba?</string> + <string name="err_point_bear_and_dist">AizpildÄ«t abus - gan virzienu, gan attÄlumu. Virziena leņķis ir no 0 lÄ«dz 360 grÄdiem attiecÄ«bÄ pret ziemeļiem. AttÄlumam nav jÄnorÄda mÄ“rvienÄ«bas.</string> + <string name="err_log_load_data">c:geo nevar ielÄdÄ“t datus, kas nepiecieÅ¡ami lai pierakstÄ«tu apmeklÄ“jumu.</string> + <string name="err_log_load_data_again">c:geo nevar ielÄdÄ“t datus, kas nepiecieÅ¡ami lai pierakstÄ«tu apmeklÄ“jumu. MÄ“Ä£iniet vÄ“lreiz. +</string> + <string name="err_log_load_data_still">c:geo joprojÄm ielÄdÄ“ datus, kas vajadzÄ«gi, lai pierakstÄ«tos. LÅ«dzu, uzgaidiet nedaudz ilgÄk.</string> + <string name="err_log_post_failed">Å Ä·iet, ka jÅ«su apmeklÄ“juma ieraksts nav pievienots. LÅ«dzu, pÄrbaudiet to slÄ“pņa mÄjas lapÄ.</string> + <string name="err_logimage_post_failed">Å Ä·iet, ka jÅ«su apmeklÄ“juma ieraksta attÄ“ls nav augÅ¡upielÄdÄ“ts. LÅ«dzu, pÄrbaudiet to slÄ“pņa mÄjas lapÄ.</string> + <string name="err_search_address_forgot">c:geo aizmirsa adresi, kuru mÄ“Ä£inÄjÄt atrast.</string> + <string name="err_parse_dist">c:geo nevar parsÄ“t attÄlumu.</string> + <string name="warn_save_nothing">Å eit nekÄ nav ko saglabÄt.</string> + <string name="warn_no_cache_coord">Te nav slÄ“pņu ar koordinÄtÄm.</string> + <string name="warn_no_coordinates">Nav dotas koordinÄtas.</string> + <string name="warn_no_keyword">Nav sniegts atslÄ“gvÄrds.</string> + <string name="warn_no_username">Nav dots lietotÄjvÄrds.</string> + <string name="warn_search_help_title">NepiecieÅ¡ama palÄ«dzÄ«ba?</string> + <string name="warn_search_help_address">Ievadiet adresi vai atraÅ¡anÄs vietas nosaukumu. PiemÄ“ram, pasta adrese \"BrÄ«vÄ«bas iela 99, RÄ«ga, Latvija\", pilsÄ“tas nosaukumu \"BerlÄ«ne\" vai tikai vietas nosaukumu - kaut ko lÄ«dzÄ«gu \"Zelta Boulings\".</string> + <string name="warn_search_help_gccode">Ievadiet kodu Ä£eoslÄ“pnim. PiemÄ“ram, \"GC1VCAZ\".</string> + <string name="warn_search_help_keyword">Ievadiet visu vai daļu Ä£eoslÄ“pņa nosaukuma. PiemÄ“ram, \"Nakts SlÄ“pnis\".</string> + <string name="warn_search_help_user">Ievadiet savu lietotÄjvÄrdu no vietnes Geocaching.com.</string> + <string name="warn_search_help_tb">Ievadiet ceļotÄja kodu, lai reÄ£istrÄ“tu atradumu. PiemÄ“ram, \"TB29QMZ\".</string> + <string name="warn_log_text_fill">LÅ«dzu, ievadi tekstu savam pierakstam.</string> + <string name="warn_load_images">c:geo neizdevÄs ielÄdÄ“t attÄ“lus.</string> + <string name="warn_nonexistant_mapfile">IzvÄ“lÄ“tais kartes fails nepastÄv. \nBezsaistes kartes nav pieejamas.</string> + <string name="warn_rendertheme_missing">Kartes tÄ“ma nav atrasta.</string> + <string name="warn_no_pocket_query_found">TieÅ¡saistÄ“ nav atrasts Pocket queries.</string> + <string name="info_log_posted">c:geo veiksmÄ«gi iesniedza pierakstu.</string> + <string name="info_log_saved">c:geo veiksmÄ«gi saglabÄja pierakstu.</string> + <string name="info_log_cleared">Ieraksts tika dzÄ“sts.</string> + <string name="info_log_type_changed">Pieraksta tips tika mainÄ«ts!</string> + <string name="info_select_logimage_cancelled">AttÄ“la atlase vai uzņemÅ¡ana tika atcelta.</string> + <string name="info_stored_image">Jauns attÄ“ls tika saglabÄts:</string> + <string name="info_storing_static_maps">CenÅ¡as saglabÄt statiskÄs kartes</string> + <string name="info_cache_saved">SlÄ“pnis ir saglabÄts bezsaistÄ“ JÅ«su ierÄ«cÄ“</string> + <string name="loc_last">PÄ“dÄ“jais zinÄmais</string> + <string name="loc_net">TÄ«kls</string> + <string name="loc_fused">KombinÄ“ts</string> + <string name="loc_low_power">Maza jauda</string> + <string name="loc_home">MÄjas koordinÄtas</string> + <string name="loc_gps">GPS</string> + <string name="loc_sat">SatelÄ«ti</string> + <string name="loc_trying">MeklÄ“ atraÅ¡anÄs vietu</string> + <string name="loc_no_addr">NezinÄma adrese</string> + <string name="loc_gps_disabled">GPS atspÄ“jots</string> + <string name="menu_centerposition">CentrÄ“t manu atraÅ¡anÄs vietu kartÄ“</string> + <string name="menu_about">Par c:geo</string> + <string name="menu_helpers">Papildus programmas</string> + <string name="menu_settings">IestatÄ«jumi</string> + <string name="menu_history">VÄ“sture</string> + <string name="menu_filter">FiltrÄ“t</string> + <string name="menu_scan_geo">SkenÄ“t Geo code</string> + <string name="menu_scan_description">c:geo var skenÄ“t Ä£eokodus, kuri tiek drukÄti kÄ QR kods. Nav instalÄ“ta nepiecieÅ¡amÄ aplikÄcija. Vai vÄ“laties atvÄ“rt Google Play (Google veikalu), lai to instalÄ“tu?</string> + <string name="live_map_button">Karte</string> + <string name="caches_nearby_button">TuvumÄ</string> + <string name="advanced_search_button">MeklÄ“t</string> + <string name="stored_caches_button">SaglabÄtie bezsaistÄ“</string> + <string name="unknown_scan">SkenÄ“Å¡anas rezultÄtÄ neviens Ä£eokods netika atrasts.</string> + <string name="caches_no_cache">Å eit nav slÄ“pņu</string> + <string name="caches_more_caches">IelÄdÄ“t vairÄk slÄ“pņus</string> + <string name="caches_more_caches_no">Vairs nav slÄ“pņu</string> + <string name="caches_more_caches_loading">IelÄdÄ“ slÄ“pņus…</string> + <string name="caches_more_caches_currently">paÅ¡laik</string> + <string name="caches_downloading">LejupielÄdÄ“ slÄ“pņus…\nETA: </string> + <string name="caches_eta_ltm">MazÄk nekÄ minÅ«te</string> + <string name="caches_store_offline">SaglabÄt bezsaistes lietoÅ¡anai</string> + <string name="caches_store_selected">SaglabÄt atlasÄ«to</string> + <string name="caches_history">VÄ“sture</string> + <string name="caches_on_map">ParÄdÄ«t kartÄ“</string> + <string name="caches_sort">KÄrtot</string> + <string name="caches_sort_distance">PÄ“c attÄluma</string> + <string name="caches_sort_difficulty">PÄ“c grÅ«tÄ«bas</string> + <string name="caches_sort_terrain">PÄ“c pieķļuves grÅ«tÄ«bas</string> + <string name="caches_sort_size">PÄ“c lieluma</string> + <string name="caches_sort_favorites">PÄ“c favorÄ«tu daudzuma</string> + <string name="caches_sort_favorites_ratio">PÄ“c favorÄ«tu [%]</string> + <string name="caches_sort_name">VÄ“c nosaukuma</string> + <string name="caches_sort_geocode">PÄ“c Geo code</string> + <string name="caches_sort_rating">PÄ“c vÄ“rtÄ“juma</string> + <string name="caches_sort_vote">Balsojums (paÅ¡a vÄ“rtÄ“jums)</string> + <string name="caches_sort_inventory">PÄ“c krÄjumu skaita</string> + <string name="caches_sort_date_hidden">PÄ“c paslÄ“pÅ¡anas datuma</string> + <string name="caches_sort_date_logged">PÄ“c pierakstÄ«Å¡anÄs datuma</string> + <string name="caches_sort_finds">PÄ“c atradumu skaita</string> + <string name="caches_sort_state">PÄ“c valsts</string> + <string name="caches_sort_storage">PÄ“c datuma, kad saglabÄts lietoÅ¡anai bezsaistÄ“ JÅ«su ierÄ«cÄ“</string> + <string name="caches_select_mode">AtzÄ«mÄ“t vairÄkus</string> + <string name="caches_select_mode_exit">Atcelt atzÄ«mÄ“Å¡anu</string> + <string name="caches_select_invert">MainÄ«t atlasi uz pretÄ“jo</string> + <string name="caches_nearby">TuvumÄ</string> + <string name="caches_manage">PÄrvaldÄ«t</string> + <string name="caches_remove_all">IzdzÄ“st visus</string> + <string name="caches_remove_selected">IzdzÄ“st atlasÄ«to</string> + <string name="caches_remove_progress">SlÄ“pņu noņemÅ¡ana</string> + <string name="caches_delete_events">PagÄjuÅ¡o notikumu dzÄ“Å¡ana</string> + <string name="caches_refresh_selected">Atjaunot atlasÄ«to</string> + <string name="caches_refresh_all">Atjaunot visu</string> + <string name="caches_move_selected">PÄrvietot atlasÄ«to</string> + <string name="caches_move_all">PÄrvietot visus</string> + <string name="caches_map_locus">Locus</string> + <string name="caches_map_locus_export">EksportÄ“t uz Locus</string> + <string name="caches_recaptcha_title">reCAPTCHA</string> + <string name="caches_recaptcha_explanation">LÅ«dzu, ievadiet attÄ“lÄ redzamo tekstu. Tas ļauj lejupielÄdÄ“t slÄ“pņu koordinÄtes, ko uzstÄdÄ«jumos var deaktivizÄ“t.</string> + <string name="caches_recaptcha_hint">Teksts no attÄ“la</string> + <string name="caches_recaptcha_continue">TurpinÄt</string> + <string name="caches_filter">FiltrÄ“t</string> + <string name="caches_filter_title">FiltrÄ“t</string> + <string name="caches_filter_size">PÄ“c lieluma</string> + <string name="caches_filter_type">PÄ“c tipa</string> + <string name="caches_filter_track">Ar ceļotÄjiem</string> + <string name="caches_filter_clear">NotÄ«rÄ«t filtrus</string> + <string name="caches_filter_modified">Ar izmainÄ«tÄm koordinÄtÄm</string> + <string name="caches_filter_origin">PÄ“c izcelsmes</string> + <string name="caches_filter_distance">PÄ“c attÄluma</string> + <string name="caches_filter_personal_note">Ar personisku piezÄ«mi</string> + <string name="caches_filter_popularity">PÄ“c favorÄ«tu daudzuma</string> + <string name="caches_filter_popularity_ratio">PÄ“c favorÄ«tu [%]</string> + <string name="caches_filter_personal_data">Ar personÄ«giem datiem</string> + <string name="caches_filter_rating">Ar reitingu</string> + <string name="caches_filter_own_rating">Ar paÅ¡a vÄ“rtÄ“jumu</string> + <string name="caches_removing_from_history">DzÄ“Å¡ no vÄ“stures…</string> + <string name="caches_clear_offlinelogs">NotÄ«rÄ«t bezsaistes ierakstus</string> + <string name="caches_clear_offlinelogs_message">Vai izdzÄ“st bezsaistes ierakstus?</string> + <string name="caches_clear_offlinelogs_progress">Bezsaistes pierakstu dzÄ“Å¡ana</string> + <string name="list_menu_create">Izveidot jaunu sarakstu</string> + <string name="list_menu_drop">Noņemt paÅ¡reizÄ“jo sarakstu</string> + <string name="list_menu_rename">PÄrdÄ“vÄ“t paÅ¡reizÄ“jo sarakstu</string> + <string name="list_menu_import">ImportÄ“t</string> + <string name="list_title">IzvÄ“lÄ“ties sarakstu</string> + <string name="list_inbox">SaglabÄtie bezsaistÄ“</string> + <string name="list_all_lists">Visi slÄ“pņi</string> + <string name="list_dialog_create_title">Jauns saraksts</string> + <string name="list_dialog_create">Izveidot</string> + <string name="list_dialog_create_ok">Tika izveidots jauns saraksts</string> + <string name="list_dialog_create_err">c:geo neizdevÄs izveidot jaunu sarakstu</string> + <string name="list_dialog_remove_title">Noņemt sarakstu</string> + <string name="list_dialog_remove_description">Vai vÄ“laties dzÄ“st paÅ¡reizÄ“jo sarakstu? Visi slÄ“pņi, kas paliks sarakstÄ, tiks pÄrvietoti uz \"SaglabÄtie\".</string> + <string name="list_dialog_remove">DzÄ“st</string> + <string name="list_dialog_remove_ok">Saraksts tika dzÄ“sts</string> + <string name="list_dialog_remove_err">c:geo neizdevÄs dzÄ“st paÅ¡reizÄ“jo sarakstu</string> + <string name="list_dialog_rename_title">PÄrdÄ“vÄ“t sarakstu</string> + <string name="list_dialog_rename">PÄrdÄ“vÄ“t</string> + <string name="list_not_available">Saraksts vairs nav pieejams, pÄrslÄ“dzas uz standarta sarakstu</string> + <string name="about_version">Versija</string> + <string name="about_changelog">Izmaiņas</string> + <string name="about_system">SistÄ“ma</string> + <string name="about_donate">Ziedot</string> + <string name="about_donation_more">Ziedot\nattÄ«stÄ«tÄjiem</string> + <string name="about_contributors">AtbalstÄ«tÄji</string> + <string name="about_license">Licences</string> + <string name="about_apache_license"><a href=""> Apache License, Version 2.0</a></string> + <string name="about_help">PalÄ«dzÄ«ba</string> + <string name="about_system_include">LÅ«dzu, iekļaujiet sekojoÅ¡u informÄciju par sistÄ“mu, nosÅ«tot kļūdas ziņojumu vai prasot vairÄk informÄcijas par c:geo:</string> + <string name="settings_title_services">Servisi</string> + <string name="settings_summary_services">KonfigurÄ“t lietotÄja konta informÄciju un papildu pakalpojumu pieejamÄ«bu.</string> + <string name="settings_title_appearance">Izskats</string> + <string name="settings_title_cachedetails">SlÄ“pņu dati</string> + <string name="settings_title_offlinedata">Bezsaistes dati</string> + <string name="settings_title_logging">PierakstÄ«Å¡anÄs</string> + <string name="settings_title_map">Karte</string> + <string name="settings_title_map_data">KarÅ¡u dati</string> + <string name="settings_title_map_content">Kartes saturs</string> + <string name="settings_title_basicmembers">IestatÄ«jumi bezmaksas lietotÄjiem</string> + <string name="settings_title_navigation">NavigÄcija</string> + <string name="settings_title_system">SistÄ“ma</string> + <string name="settings_title_navigation_menu">NavigÄcijas izvÄ“lne</string> + <string name="settings_category_browser">PÄrlÅ«kprogramma</string> + <string name="settings_category_social">Social media</string> + <string name="settings_category_logging_other">Citi pierakstÄ«Å¡anÄs iestatÄ«jumi</string> + <string name="settings_goto_url_button">vairÄk…</string> + <string name="settings_title_ec">Extremcaching.com</string> + <string name="settings_activate_gc">AktivizÄ“t</string> + <string name="settings_activate_ec">AktivizÄ“t</string> + <string name="settings_activate_ox">AktivizÄ“t</string> + <string name="settings_gc_legal_note">Izmantojot geocaching.com pakalpojumu, jÅ«s piekrÄ«tat Groundspeak lietoÅ¡anas noteikumiem.</string> + <string name="settings_info_facebook_login_title">Facebook Login</string> + <string name="settings_info_facebook_login">Nevar veikt c:geo pieteikÅ¡anÄs ar savu Facebook kontu iekÅ¡ geocaching.com. Bet tur ir vienkÄrÅ¡s risinÄjums…</string> + <string name="settings_authorize">Atļaut c:geo</string> + <string name="settings_reauthorize">Atkal atļaut c:geo</string> + <string name="settings_activate_oc">AktivizÄ“t</string> + <string name="init_oc_de_description">Atļaut c:geo un opencaching.de meklÄ“t slÄ“pņus un piekļūt/filtrÄ“t savus atrastos slÄ“pņus.</string> + <string name="settings_activate_oc_pl">AktivizÄ“t</string> + <string name="init_oc_pl_description">Atļaut c:geo un opencaching.pl meklÄ“t slÄ“pņus un piekļūt/filtrÄ“t savus atrastos slÄ“pņus.</string> + <string name="settings_activate_oc_nl">AktivizÄ“t</string> + <string name="init_oc_nl_description">Atļaut c:geo un opencaching.nl meklÄ“t slÄ“pņus un piekļūt/filtrÄ“t savus atrastos slÄ“pņus.</string> + <string name="settings_activate_oc_us">AktivizÄ“t</string> + <string name="init_oc_us_description">Atļaut c:geo un opencaching.us meklÄ“t slÄ“pņus un piekļūt/filtrÄ“t savus atrastos slÄ“pņus.</string> + <string name="settings_activate_oc_ro">AktivizÄ“t</string> + <string name="init_oc_ro_description">Atļaut c:geo un opencaching.ro meklÄ“t slÄ“pņus un piekļūt/filtrÄ“t savus atrastos slÄ“pņus.</string> + <string name="settings_activate_oc_uk">AktivizÄ“t</string> + <string name="init_oc_uk_description">Atļaut c:geo un opencaching.org.uk meklÄ“t slÄ“pņus un piekļūt/filtrÄ“t savus atrastos slÄ“pņus.</string> + <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Lai spÄ“tu novÄ“rtÄ“t slÄ“pni, jums jÄseko instrukcijÄm GCVote.com mÄjas lapÄ un jÄievada jÅ«su GCVote parole Å¡eit.</string> + <string name="gcvote_sent">Balsojums veiksmÄ«gi nosÅ«tÄ«ts</string> + <string name="init_twitter">Twitter</string> + <string name="settings_activate_twitter">AktivizÄ“t</string> + <string name="init_username">LietotÄjvÄrds</string> + <string name="init_password">Parole</string> + <string name="init_login">PÄrbaudÄ«t pieteikÅ¡anos</string> + <string name="init_login_popup">PieteikÅ¡anÄs</string> + <string name="init_login_popup_working">PiesakÄs sistÄ“mÄ…</string> + <string name="init_login_popup_ok">PieteikÅ¡anÄs izpildÄ«ta veiksmÄ«gi</string> + <string name="init_login_popup_failed">PieteikÅ¡anÄs neizdevÄs</string> + <string name="init_login_popup_failed_reason">PieteikÅ¡anÄs neizdevÄs:</string> + <string name="init_login_popup_not_authorized">Nav autorizÄ“ts</string> + <string name="init_login_popup_invalid_timestamp">VietÄ“jais laiks nepareizs, pielÄgot ierÄ«ces laiku</string> + <string name="init_login_popup_invalid_token">Atļauja nederÄ«ga, atkÄrtoti mÄ“Ä£iniet autorizÄ“ties</string> + <string name="settings_service_active">AktÄ«vs</string> + <string name="init_signature">Paraksts</string> + <string name="init_template_help">IestarpinÄjumi, piemÄ“ram, [NAME] tiks paplaÅ¡inÄts vÄ“lÄk lietojot Å¡o sagatavi.</string> + <string name="init_signature_template_button">Ievietot sagatavi</string> + <string name="init_signature_template_date">Datums</string> + <string name="init_signature_template_time">Laiks</string> + <string name="init_signature_template_datetime">Datums & laiks</string> + <string name="init_signature_template_user">LietotÄjs</string> + <string name="init_signature_template_number">Numurs</string> + <string name="init_signature_template_owner">ĪpaÅ¡nieks</string> + <string name="init_signature_template_name">VÄrds</string> + <string name="init_signature_template_url">URL</string> + <string name="init_signature_template_log">Ieraksta teksts</string> + <string name="init_ratingwanted">GCvote reitings</string> + <string name="init_friends_and_own_logs_wanted">RÄdÄ«t draugu / savus</string> + <string name="init_summary_friends_and_own_logs_wanted">RÄdÄ«t papildu lapu ar draugu un saviem apmeklÄ“juma ierakstiem</string> + <string name="init_autoload">Pilns apraksts</string> + <string name="init_summary_autoload">VienmÄ“r ielÄdÄ“t pilnu aprakstu</string> + <string name="init_skin">GaiÅ¡s fons</string> + <string name="init_summary_skin">Izmantot gaiÅ¡u fonu (nepiecieÅ¡ama restartÄ“Å¡ana)</string> + <string name="init_address">RÄdÄ«t adresi</string> + <string name="init_summary_address">RÄdÄ«t adresi, nevis koordinÄtes galvenajÄ ekrÄnÄ</string> + <string name="init_captcha">RÄdÄ«t CAPTCHA</string> + <string name="init_useenglish">Lietot angļu valodu</string> + <string name="init_summary_useenglish">Izmantot angļu valodu c:geo (nepiecieÅ¡ama restartÄ“Å¡ana)</string> + <string name="init_exclude">NerÄdÄ«t savus un atrastos</string> + <string name="init_summary_exclude">NerÄdÄ«t jÅ«su paÅ¡u vai jau atrastos slÄ“pņus</string> + <string name="init_showwaypoints">RÄdÄ«t Starpposmus</string> + <string name="init_showwaypoint_description">Ja skaits ir mazÄks nekÄ norÄdÄ«tais attÄ“lojamo slÄ“pņu skaits, tad papildus kartÄ“ tiek parÄdÄ«ti arÄ« to Starpposmi.</string> + <string name="init_summary_offline_wp">SaglabÄt Starpposmu statiskÄs kartes lietoÅ¡anai bezsaistÄ“</string> + <string name="init_save_log_img">SaglabÄt attÄ“lus</string> + <string name="init_log_offline">Bezsaistes apmeklÄ“juma reÄ£istrÄcija</string> + <string name="init_summary_log_offline">IespÄ“jot bezsaistes pierakstÄ«Å¡anos (nerÄdÄ«s tieÅ¡saistes pieteikÅ¡anÄs logu ekrÄnÄ, kad reÄ£istrÄ“ atradumu, netiks augÅ¡upielÄdÄ“ti pieraksta teksti)</string> + <string name="init_livelist">RÄdÄ«t virzienu</string> + <string name="init_summary_livelist">RÄdÄ«t slÄ“pņu virzienus sarakstÄ</string> + <string name="init_backup">Rezerves kopija</string> + <string name="init_backup_backup">Izveidot rezerves kopiju</string> + <string name="init_backup_running">Notiek slÄ“pņu rezerves kopijas izveide…</string> + <string name="init_backup_note">LÅ«dzu, ņemiet vÄ“rÄ, ka Å¡is funkcija atjaunos datu bÄzi, kas satur slÄ“pņu un Starpposmu, bet ne jÅ«su iestatÄ«jumus.\nYour pieteikÅ¡anÄs dati un paroles nekÄdÄ gadÄ«jumÄ nepazudÄ«s no aplikÄcijas datiem.</string> + <string name="init_backup_restore">Atjaunot</string> + <string name="init_restore_failed">AtjaunoÅ¡ana neizdevÄs.</string> + <string name="init_restore_confirm">DatubÄze ir tukÅ¡a. Vai vÄ“laties atjaunot datubÄzes dublÄ“jumu?</string> + <string name="init_backup_last">Pieejams dublÄ“jums no</string> + <string name="settings_info_offline_maps_title">Info uz bezsaistes kartÄ“m</string> + <string name="settings_info_offline_maps">c:geo atbalsta kartes lietoÅ¡anai bezsaistÄ“. JÅ«s varat lejupielÄdÄ“t kartes no Mapsforge vai pat izveidot savas kartes no OSM datiem. Vispirms jÄatlasa bezsaistes karÅ¡u direktorija, lai iegÅ«tu karti ar bezsaistes atbalstu.</string> + <string name="init_mapsource_select">IzvÄ“lies karti</string> + <string name="init_gpx_exportdir">GPX eksporta direktorija</string> + <string name="init_gpx_importdir">GPX importa direktorija</string> + <string name="init_maptrail">ParÄdÄ«t pÄrvietojumu</string> + <string name="init_summary_maptrail">ParÄdÄ«t pÄrvietojumu kartÄ“</string> + <string name="init_share_after_export">AtvÄ“rt koplietoÅ¡anas izvÄ“lni pÄ“c GPX eksporta</string> + <string name="init_trackautovisit">CeļotÄju automÄtiska atzÄ«mÄ“Å¡ana</string> + <string name="init_summary_trackautovisit">PÄ“c noklusÄ“juma uzlikt ceļotÄjam statusu \"ApmeklÄ“jis\" (\"VIsited\")</string> + <string name="init_sigautoinsert">Ievietot automÄtiski</string> + <string name="init_loaddirectionimg">Virziena attÄ“ls</string> + <string name="init_summary_loaddirectionimg">LejupielÄdÄ“t virziena bultiņas attÄ“lu pÄ“c nepiecieÅ¡amÄ«bas (nepiecieÅ¡ams tikai bezmaksas lietotÄjam)</string> + <string name="init_default_navigation_tool">NoklusÄ“juma navigÄcija</string> + <string name="init_secondary_navigation_tool">SekundÄrÄ navigÄcija</string> + <string name="init_default_navigation_tool_description">Å eit jÅ«s varat izvÄ“lÄ“ties primÄro navigÄcijas rÄ«ku.</string> + <string name="init_default_navigation_tool_select">IzvÄ“lies rÄ«ku</string> + <string name="init_default_navigation_tool_2_description">Å eit var izvÄ“lÄ“ties sekundÄro navigÄcijas rÄ«ku. AktivizÄ“jiet to ilgi turot nospiestu navigÄcijas ikonu blakus slÄ“pņa nosaukumam.</string> + <string name="init_navigation_menu_description">Å eit var atlasÄ«t, kuras pieejamÄs navigÄcijas metodes tiks parÄdÄ«tas navigÄcijas izvÄ“lnÄ“ slÄ“pnim vai starpposmam. NeaktÄ«vie rÄ«ki nav instalÄ“ti Å¡ajÄ ierÄ«cÄ“.</string> + <string name="init_debug_title">AtkļūdoÅ¡anas informÄcija</string> + <string name="init_dbonsdcard_title">Datu bÄzes atraÅ¡anÄs vieta</string> + <string name="init_dbonsdcard_note">c:geo datu bÄze var tikt saglabÄt ÄrÄ“jÄ glabÄÅ¡anas vietÄ. Darot to, tas ļaus ietaupÄ«t iekÅ¡Ä“jo atmiņu, bet jÅ«s varat mazliet zaudÄ“t ÄtrdarbÄ«bu un c:geo nedarbosies, ja SD karte nav pieejama.</string> + <string name="init_dbonsdcard">Ä€rÄ“jÄ glabÄÅ¡anas vietÄ</string> + <string name="init_dbmove_dbmove">Tiek pÄrvietota datu bÄze</string> + <string name="init_dbmove_running">Tiek pÄrvietota datu bÄze</string> + <string name="init_dbmove_success">Datu bÄze ir veiksmÄ«gi pÄrvietota.</string> + <string name="init_dbmove_failed">NeizdevÄs pÄrvietot datu bÄzi</string> + <string name="init_plain_logs">VienkÄrÅ¡i ieraksti</string> + <string name="init_summary_plain_logs">AttÄ“lot ierakstus bezkrÄsainus</string> + <string name="init_use_native_ua">Android pÄrlÅ«kprogramma</string> + <string name="init_summary_use_native_ua">IdentificÄ“t kÄ Android pÄrlÅ«kprogrammu.Atrisina pierakstÄ«Å¡anÄs problÄ“mas, lietojot dažÄdus tÄ«kla pakalpojumu sniedzÄ“jus.</string> + <string name="init_rendertheme_folder">KarÅ¡u tÄ“mu direktorija</string> + <string name="init_maintenance">UzturÄ“Å¡ana</string> + <string name="init_maintenance_directories_note">c:geo saglabÄ attÄ“lus, apmeklÄ“juma ierakstu attÄ“lus un citus failus, kas saistÄ«ti ar slÄ“pni atseviÅ¡Ä·Ä direktorijÄ. Dažos gadÄ«jumos (piemÄ“ram, importÄ“jot/eksportÄ“jot datu bÄzi) Å¡ajÄ direktorijÄ var bÅ«t novecojuÅ¡i faili, kuri Å¡eit var tikt dzÄ“sti.</string> + <string name="init_maintenance_directories">DzÄ“st failus, kas palikuÅ¡i nevajadzÄ«gi (novecojuÅ¡i)</string> + <string name="init_location">Ä¢eolokÄcija</string> + <string name="init_location_note">IerÄ«cÄ“s, kas aprÄ«koti ar Google Play pakalpojumiem, c:geo automÄtiski var izmantot labÄku Ä£eolokÄcijas nodroÅ¡inÄtÄju. TomÄ“r tas neļauj izmantot ÄrÄ“jo BlueTooth GPS uztvÄ“rÄ“ju.</string> + <string name="init_location_googleplayservices">Izmantt Google Play pakalpojumus</string> + <string name="init_low_power">Mazjaudas režīms</string> + <string name="init_low_power_note">Mazjaudas režīms novÄ“rÅ¡ GPS un žiroskopa izmantoÅ¡anu, kad ļoti precÄ«za atraÅ¡anÄs vieta nav absolÅ«ti nepiecieÅ¡ama, patÄ“rÄ“ daudz vairÄk laika noteikÅ¡anai.</string> + <string name="init_low_power_mode">AktivizÄ“t mazjaudas režīmu</string> + <string name="init_create_memory_dump">Izveidot atmiņas izrakstu</string> + <string name="init_memory_dump">Atmiņas izraksts</string> + <string name="init_memory_dumped">Atmiņas izraksts %s</string> + <string name="init_hardware_acceleration_title">AparatÅ«ras paÄtrinÄta renderÄ“Å¡ana</string> + <string name="init_hardware_acceleration_note">AparatÅ«ras paÄtrinÄÅ¡ana renderÄ“ grafiskos elementus ÄtrÄk uz ekrÄna. TomÄ“r dažas Android operÄ“tÄjsistÄ“mas ierÄ«ces rada tehnisku kļūdu un daži teksti var parÄdÄ«ties neskaidrs (Ä«paÅ¡i treknraksta rakstzÄ«mÄ“m). AtspÄ“jojiet aparatÅ«ras paÄtrinÄÅ¡anu, ja tas jums notiek.</string> + <string name="init_hardware_acceleration">IespÄ“jot aparatÅ«ras paÄtrinÄÅ¡anu</string> + <string name="settings_open_website">AtvÄ“rt vietni</string> + <string name="settings_settings">IestatÄ«jumi</string> + <string name="settings_information">InformÄcija</string> + <string name="settings_twitter_cache_message">Ziņojums par atrastu slÄ“pni</string> + <string name="settings_twitter_trackable_message">Ziņojums par atrastu ceļotÄju</string> + <string name="init_ec_icons">Kartes ikonas</string> + <string name="settings_ec_icons_other">Savs stils</string> + <string name="settings_ec_icons_oc">PiemÄ“ram, OC</string> + <string name="settings_features">AtbalstÄ«tÄs funkcijas</string> + <string name="feature_description">Å Ädas <b>tieÅ¡saistes</b> funkcijas Å¡ajÄ mÄjas lapÄ tiek atbalstÄ«tas iekÅ¡ c:geo (papildus bezsaistes funkcijÄm):</string> + <string name="feature_personal_notes">Personiska piezÄ«me</string> + <string name="feature_online_logging">TieÅ¡saistes pierakstÄ«Å¡anÄs</string> + <string name="feature_log_images">Pievienot attÄ“lus ierakstam</string> + <string name="feature_watch_list">SkatÄ«ties sarakstu</string> + <string name="feature_own_coordinates">SaglabÄt modificÄ“tÄs koordinÄtas</string> + <string name="feature_search_keyword">MeklÄ“t pÄ“c atslÄ“gvÄrda</string> + <string name="feature_search_live_map">TIeÅ¡saistes karte</string> + <string name="feature_search_center">MeklÄ“t pÄ“c atraÅ¡anÄs vietas</string> + <string name="feature_search_geocode">MeklÄ“t pÄ“c Geo code</string> + <string name="feature_search_owner">MeklÄ“t pÄ“c Ä«paÅ¡nieka</string> + <string name="feature_search_finder">MeklÄ“t pÄ“c atradÄ“ja</string> + <string name="map_source_google_map">Google: Map</string> + <string name="map_source_google_satellite">Google: Satellite</string> + <string name="map_source_osm_mapnik">OSM: Mapnik</string> + <string name="map_source_osm_cyclemap">OSM: Cyclemap</string> + <string name="map_source_osm_offline">Bezsaistes režīmÄ</string> + <string name="init_sendToCgeo">Send to c:geo</string> + <string name="settings_info_send2cgeo_title">Info par send2cgeo</string> + <string name="init_sendToCgeo_name">JÅ«su ierÄ«ces nosaukums</string> + <string name="init_sendToCgeo_register">PieprasÄ«t reÄ£istrÄciju</string> + <string name="init_sendToCgeo_register_ok">ReÄ£istrÄcija veiksmÄ«ga. PIN kods ir ####. Izmantojiet to tÄ«mekļa vietnÄ“ c:geo, lai pieslÄ“gtos ar Å¡o ierÄ«ci jÅ«su pÄrlÅ«kprogrammÄ.</string> + <string name="init_sendToCgeo_register_fail">ReÄ£istrÄcija neizdevÄs.</string> + <string name="auth_twitter">Twitter</string> + <plurals name="cache_counts"> + <item quantity="zero">%1$d slÄ“pnis</item> + <item quantity="one">%1$d slÄ“pnis</item> + <item quantity="other">%1$d slÄ“pņi</item> + </plurals> + <string name="cache_offline">Bezsaistes režīmÄ</string> + <string name="cache_offline_refresh">Atjaunot</string> + <string name="cache_offline_drop">Izmest</string> + <string name="cache_offline_store">SaglabÄt</string> + <string name="cache_offline_stored">SaglabÄtie bezsaistÄ“ JÅ«su ierÄ«cÄ“</string> + <string name="cache_offline_not_ready">Nav pieejams bezsaistÄ“</string> + <string name="cache_offline_time_about">pirms</string> + <string name="cache_offline_time_mins">minÅ«tes (-Ä“m)</string> + <string name="cache_offline_time_mins_few">dažas minÅ«tes atpakaļ</string> + <string name="cache_offline_time_hour">pirms stundas</string> + <string name="cache_offline_time_hours">stundas (-Äm)</string> + <string name="cache_offline_time_days">dienu (-as)</string> + <string name="cache_premium">Premium</string> + <string name="cache_attributes">AtribÅ«ti</string> + <string name="cache_inventory">KrÄjumi</string> + <string name="cache_log_images_title">ApmeklÄ“juma attÄ“li</string> + <string name="cache_log_image_default_title">AttÄ“ls</string> + <string name="cache_personal_note">Personiska piezÄ«me</string> + <string name="cache_personal_note_edit">Rediģēt</string> + <string name="cache_personal_note_limit">PersoniskÄs piezÄ«mes limits</string> + <string name="cache_personal_note_truncation">Å Ä« personiskÄ piezÄ«me tiks apcirsta iekÅ¡ Geocaching.com pÄ“c %d rakstzÄ«mju.</string> + <string name="cache_personal_note_upload">AugÅ¡upielÄdÄ“t</string> + <string name="cache_personal_note_upload_cancelled">PersoniskÄs piezÄ«mes ielÄde atcelta</string> + <string name="cache_description">Apraksts</string> + <string name="cache_description_long">GarÅ¡ apraksts</string> + <string name="cache_watchlist_on">JÅ«s novÄ“rojat Å¡o slÄ“pni</string> + <string name="cache_watchlist_not_on">Å is slÄ“pnis nav jÅ«su sarakstÄ ar novÄ“rojamajiem.</string> + <string name="cache_watchlist_add">Pievienot sarakstam ar novÄ“rojamajiem</string> + <string name="cache_watchlist_remove">Noņemt no saraksta ar novÄ“rojamajiem</string> + <string name="cache_favpoint_on">Å is slÄ“pnis ir viens no jÅ«su favorÄ«tiem.</string> + <string name="cache_favpoint_not_on">Å is slÄ“pnis nav neviens no jÅ«su favorÄ«tiem.</string> + <string name="cache_favpoint_add">Pievienot</string> + <string name="cache_favpoint_remove">Noņemt</string> + <string name="cache_list_text">Saraksts:</string> + <string name="cache_list_change">PÄrvietot</string> + <string name="cache_list_unknown">Nav sarakstÄ</string> + <string name="cache_images">AttÄ“li</string> + <string name="cache_waypoints">Starpposmi</string> + <plurals name="waypoints"> + <item quantity="zero">%d Starpposms</item> + <item quantity="one">%d Starpposms</item> + <item quantity="other">%d Starpposmi</item> + </plurals> + <string name="cache_waypoints_add">Pievienot Starpposmu</string> + <string name="cache_hint">MÄjiens</string> + <string name="cache_logs">ApmeklÄ“jumu žurnÄls</string> + <string name="cache_logs_friends_and_own">Draugu/paÅ¡a ieraksti</string> + <string name="cache_dialog_loading_details">IelÄdÄ“ slÄ“pņa datus…</string> + <string name="cache_dialog_loading_details_status_loadpage">IelÄdÄ“ lapu</string> + <string name="cache_dialog_loading_details_status_details">ApstrÄdÄ detaļas</string> + <string name="cache_dialog_loading_details_status_spoilers">IelÄdÄ“ \"spoiler\" attÄ“lus</string> + <string name="cache_dialog_loading_details_status_logs">IelÄdÄ“ ierakstus</string> + <string name="cache_dialog_loading_details_status_waypoints">ApstrÄdÄ Starpposmus</string> + <string name="cache_dialog_loading_details_status_gcvote">IelÄdÄ“ GCVote</string> + <string name="cache_dialog_loading_details_status_cache">Apkopo datus</string> + <string name="cache_dialog_loading_details_status_render">Gatavo attÄ“loÅ¡anai</string> + <string name="cache_dialog_offline_save_title">Bezsaistes režīmÄ</string> + <string name="cache_dialog_offline_save_message">SaglabÄ slÄ“pni bezsaistes lietoÅ¡anai…</string> + <string name="cache_dialog_offline_drop_title">Bezsaistes režīmÄ</string> + <string name="cache_dialog_offline_drop_message">Notiek slÄ“pņa izdzÄ“Å¡ana no ierÄ«ces atmiņas…</string> + <string name="cache_dialog_refresh_title">Atjaunot</string> + <string name="cache_dialog_watchlist_add_title">Saraksts ar novÄ“rojamajiem</string> + <string name="cache_dialog_watchlist_add_message">Notiek slÄ“pņa pievienoÅ¡ana novÄ“rojamo slÄ“pņu sarakstam…</string> + <string name="cache_dialog_watchlist_remove_title">Saraksts ar novÄ“rojamajiem</string> + <string name="cache_dialog_watchlist_remove_message">Notiek slÄ“pņa dzÄ“Å¡ana no novÄ“rojamo slÄ“pņu saraksta…</string> + <string name="cache_dialog_favorite_add_title">FavorÄ«ts</string> + <string name="cache_dialog_favorite_add_message">Pievienot slÄ“pni favorÄ«tiem…</string> + <string name="cache_dialog_favorite_remove_title">FavorÄ«ts</string> + <string name="cache_dialog_favorite_remove_message">Noņemt slÄ“pni no saviem favorÄ«tiem…</string> + <string name="cache_menu_radar">Radars</string> + <string name="cache_menu_map">Karte</string> + <string name="cache_menu_map_static">StatiskÄs kartes</string> + <string name="cache_menu_streetview">Ielas skats (Street View)</string> + <string name="cache_menu_browser">AtvÄ“rt pÄrlÅ«kprogrammÄ</string> + <string name="cache_menu_visit">ReÄ£istrÄ“t atradumu</string> + <string name="cache_menu_visit_offline">Viena klikÅ¡Ä·a bezsaistes apmeklÄ“juma reÄ£istrÄcija</string> + <string name="cache_menu_spoilers">\"Spoiler\" bilde (-es)</string> + <string name="cache_menu_event">Pievienot kalendÄram</string> + <string name="cache_menu_details">SÄ«kÄka informÄcija</string> + <string name="cache_menu_refresh">AtsvaidzinÄt</string> + <string name="cache_menu_move_list">PÄrvietot uz citu sarakstu</string> + <string name="cache_menu_whereyougo">WhereYouGo</string> + <string name="cache_menu_oruxmaps">OruxMaps</string> + <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Balsot</string> + <string name="cache_status">Statuss</string> + <string name="cache_status_offline_log">ApmeklÄ“jums ieraksts saglabÄts</string> + <string name="cache_status_found">Atrasts</string> + <string name="cache_not_status_found">Nav atrasts</string> + <string name="cache_status_archived">ArhivÄ“ts</string> + <string name="cache_status_disabled">AtspÄ“jots</string> + <string name="cache_status_premium">TIkai Premium lietotÄjiem</string> + <string name="cache_status_not_premium">Pieejams visiem lietotÄjiem</string> + <string name="cache_status_stored">SaglabÄts</string> + <string name="cache_status_not_stored">Nav saglabÄti</string> + <string name="cache_geocode">Geo code</string> + <string name="cache_name">Nosaukums</string> + <string name="cache_type">Tips</string> + <string name="cache_size">IzmÄ“rs</string> + <string name="cache_distance">AttÄlums</string> + <string name="cache_difficulty">GrÅ«tÄ«ba</string> + <string name="cache_terrain">Pieķļuve</string> + <string name="cache_rating">VÄ“rtÄ“jums</string> + <string name="cache_own_rating">JÅ«su vÄ“rtÄ“jums</string> + <string name="cache_favorite">FavorÄ«ti</string> + <string name="cache_owner">ĪpaÅ¡nieks</string> + <string name="cache_hidden">PaslÄ“pts</string> + <string name="cache_location">AtraÅ¡anÄs vieta</string> + <string name="cache_coordinates">KoordinÄtas</string> + <string name="cache_coordinates_original">SÄkotnÄ“jÄs koordinÄtas</string> + <string name="cache_spoiler_images_title">\"Spoiler\" bilde (-es)</string> + <string name="cache_log_types">ReÄ£istrÄ“to ierakstu tipi</string> + <string name="cache_coordinates_no">Å im slÄ“pnim nav koordinÄtu.</string> + <string name="cache_clear_history">NotÄ«rÄ«t vÄ“sturi</string> + <string name="cache_remove_from_history">Noņemt no vÄ“stures</string> + <string name="cache_license">Licence</string> + <string name="cache_image">AttÄ“ls</string> + <string name="cache_image_open_file">AtvÄ“rt kÄ failu</string> + <string name="cache_image_open_browser">AtvÄ“rt pÄrlÅ«kprogrammÄ</string> + <string name="gpx_import_loading_waypoints">IelÄdÄ“ Starpposmu failu</string> + <string name="gpx_import_title_caches_import_failed">ImportÄ“Å¡ana neizdevÄs</string> + <string name="gpx_import_error_io">Nevar nolasÄ«t failu</string> + <string name="gpx_import_error_parser">Nepareizs faila formÄts</string> + <string name="gpx_import_error_unexpected">NeparedzÄ“ta kļūda</string> + <string name="gpx_import_canceled">GPX importÄ“Å¡ana tika atcelta</string> + <string name="gpx_import_delete_title">DzÄ“st failu</string> + <string name="gpx_import_delete_message">Vai vÄ“laties dzÄ“st %s?</string> + <string name="waypoint">Starpposms</string> + <string name="waypoint_cache_coordinates">SlÄ“pņa koordinÄtas</string> + <string name="waypoint_custom">UzstÄdÄ«t</string> + <string name="waypoint_my_coordinates">Manas koordinÄtas</string> + <string name="waypoint_bearing">Pagrieziena leņķis °</string> + <string name="waypoint_distance">AttÄlums</string> + <string name="waypoint_name">Nosaukums</string> + <string name="waypoint_edit">Rediģēt</string> + <string name="waypoint_delete">DzÄ“st</string> + <string name="waypoint_edit_title">Rediģēt Starpposmu</string> + <string name="waypoint_add_title">Pievienot Starpposmu</string> + <string name="waypoint_note">PiezÄ«me</string> + <string name="waypoint_visited">ApmeklÄ“ts</string> + <string name="waypoint_save">SaglabÄt</string> + <string name="waypoint_loading">Notiek Starpposma ielÄde…</string> + <string name="waypoint_do_not_touch_cache_coordinates">NeizmainÄ«t slÄ“pņa koordinÄtas</string> + <string name="waypoint_set_as_cache_coords">IestatÄ«t kÄ slÄ“pņa koordinÄtas iekÅ¡ c:geo</string> + <string name="waypoint_save_and_modify_on_website">IestatÄ«t kÄ slÄ“pņa koordinÄtas c:geo un mÄjas lapÄ</string> + <string name="waypoint_reset_cache_coords">AtiestatÄ«t slÄ“pņa koordinÄtas</string> + <string name="waypoint_coordinates_has_been_reset_on_website">SlÄ“pņa koordinÄtas ir atiestatÄ«tas mÄjas lapÄ.</string> + <string name="waypoint_coordinates_being_reset_on_website">AtiestatÄ«t slÄ“pņa koordinÄtas mÄjas lapÄ…</string> + <string name="waypoint_reset">AtiestatÄ«t</string> + <string name="waypoint_localy_reset_cache_coords">AtiestatÄ«t iekÅ¡ c:geo</string> + <string name="waypoint_reset_local_and_remote_cache_coords">AtiestatÄ«t iekÅ¡ c:geo un mÄjas lapÄ</string> + <string name="waypoint_being_saved">Starpposms tiek saglabÄts</string> + <string name="waypoint_coordinates_couldnt_be_modified_on_website">MÄjas lapa neatbalsta slÄ“pņa koordinÄtu modificÄ“Å¡anu.</string> + <string name="waypoint_coordinates_upload_error">ModificÄ“jot koordinÄtas mÄjas lapÄ, radÄs kļūda.</string> + <string name="waypoint_coordinates_uploading_to_website">Tiek augÅ¡upielÄdÄ“tas koordinÄtas %s mÄjas lapÄ.</string> + <string name="waypoint_coordinates_has_been_modified_on_website">SlÄ“pņa koordinÄtas mÄjas lapÄ tika modificÄ“tas uz: %s.</string> + <string name="waypoint_done">IzpildÄ«ts</string> + <string name="waypoint_duplicate">DublicÄ“t</string> + <string name="waypoint_copy_of">Kopija</string> + <string name="search_history">VÄ“sture</string> + <string name="waypoint_coordinate_formats_plain">VienkÄrÅ¡Ä</string> + <string name="map_map">Karte</string> + <string name="map_view_map">Kartes skats</string> + <string name="map_modes">Kartes iestatÄ«jumi</string> + <string name="map_mycaches_hide">NerÄdÄ«t savus/atrastos slÄ“pņus</string> + <string name="map_live_enable">Atļaut tieÅ¡saistÄ“</string> + <string name="map_live_disable">DeaktivizÄ“t tieÅ¡saistes darbÄ«bu</string> + <string name="map_strategy_fastest">Ä€trÄkais</string> + <string name="map_strategy_fast">Ä€trs</string> + <string name="map_strategy_auto">AtkarÄ«bÄ no Ätruma</string> + <string name="map_strategy_detailed">DetalizÄ“ts</string> + <string name="search_coordinates">KoordinÄtas</string> + <string name="search_address">Adrese</string> + <string name="search_address_button">MeklÄ“t pÄ“c adreses</string> + <string name="search_hbu_button">MeklÄ“t pÄ“c Ä«paÅ¡nieka vÄrda</string> + <string name="search_tb">CeļotÄjs</string> + <string name="search_tb_button">MeklÄ“t ceļotÄju</string> + <string name="search_direction_rel">No Å¡Ä«s pozÄ«cijas</string> + <string name="search_address_started">MeklÄ“ vietu</string> + <string name="search_own_caches">MeklÄ“t manus slÄ“pņus</string> + <string name="trackable_log_touch">PierakstÄ«t pieskÄrienu</string> + <string name="trackable_name">Nosaukums</string> + <string name="trackable_type">Veids</string> + <string name="trackable_owner">ĪpaÅ¡nieks</string> + <string name="trackable_spotted">PamanÄ«ts</string> + <string name="trackable_spotted_in_cache">IekÅ¡</string> + <string name="trackable_spotted_at_user">RokÄs</string> + <string name="trackable_spotted_unknown_location">AtraÅ¡anÄs nav zinÄma</string> + <string name="trackable_spotted_owner">Pie Ä«paÅ¡nieka</string> + <string name="trackable_touch">Pieskarties</string> + <string name="user_menu_send_message">NosÅ«tÄ«t ziņu</string> + <string name="navigation">NavigÄcija</string> + <string name="compass_title">Kompass</string> + <string name="compass_sensors">AktÄ«vie sensori</string> + <string name="use_gps">Izmantot tikai GPS</string> + <string name="use_compass">Izmantot GPS un kompasu</string> + <string name="destination_select">IzvÄ“lieties galamÄ“rÄ·i</string> + <string name="navigation_target">MÄ“rÄ·is</string> + <string name="err_nav_no_coordinates">Nevar sÄkt navigÄciju bez koordinÄtÄ“m</string> + <string name="license">Licence</string> + <string name="license_show">RÄdÄ«t licenci</string> + <string name="helper_barcode_description">Å ie ir Greasemonkey skripti un tÄ«mekļa vietnes, kas ļauj parÄdÄ«t Ä£eokodus kÄ svÄ«trkodus. Ar Å¡o aplikÄciju c:geo var lasÄ«t Å¡Ädu Ä£eokodus tieÅ¡i no datora ekrÄna.</string> + <string name="helper_pocketquery_description">Atļauj viegli izveidot un lejupielÄdÄ“t no Pocket Query, kas centrÄ“ts uz Tavu paÅ¡reizÄ“jo atraÅ¡anÄs vietu vai atlasÄ«ts no punkta kartÄ“. NepiecieÅ¡ams Geocaching.com Premium lietotÄja konts.</string> + <string name="export_fieldnotes_upload">AugÅ¡upielÄdÄ“t geocaching.com</string> + <string name="attribute_motorcycles_yes">Motocikli atļauti</string> + <string name="attribute_motorcycles_no">Motocikli nav atļauti</string> + <string name="attribute_firstaid_yes">NepiecieÅ¡ama apkope</string> + <string name="attribute_wheelchair_yes">Pieejams ratiņkrÄ“slÄ</string> + <string name="attribute_wheelchair_no">Nav pieejams ratiņkrÄ“slÄ</string> + <string name="attribute_water_yes">TuvumÄ dzeramais Å«dens</string> + <string name="attribute_water_no">TuvumÄ dzeramÄ Å«dens nav</string> + <string name="attribute_restrooms_yes">PubliskÄs tualetes tuvumÄ</string> + <string name="attribute_restrooms_no">TuvumÄ nav publiskÄs tualetes</string> + <string name="attribute_phone_yes">Telefona tuvumÄ</string> + <string name="attribute_phone_no">Telefona tuvumÄ nav</string> + <string name="attribute_picnic_yes">Piknika galdiņi netÄlu</string> + <string name="attribute_picnic_no">Piknika galdiņu nav</string> + <string name="attribute_fuel_yes">DUS tuvumÄ</string> + <string name="attribute_fuel_no">DUS tuvumÄ nav</string> + <string name="attribute_food_yes">Ä’dinÄÅ¡ana tuvumÄ</string> + <string name="attribute_food_no">Ä’dinÄÅ¡anas tuvumÄ nav</string> + <string name="attribute_railway_yes">TuvumÄ darbojoÅ¡Äs sliedes</string> + <string name="attribute_railway_no">TuvumÄ darbojoÅ¡Äs sliedes nav</string> + <string name="attribute_webcam_yes">TÄ«mekļa kamera</string> + <string name="attribute_webcam_no">Nav tÄ«mekļa kameras</string> + <string name="attribute_puzzle_yes">Puzzle / MistÄ“rijas slÄ“pnis</string> + <string name="attribute_puzzle_no">Nav puzzle / mistÄ“rija</string> + <string name="tts_one_meter">viens metrs</string> + <plurals name="tts_meters"> + <item quantity="zero">%s m</item> + <item quantity="one">%s metrs</item> + <item quantity="other">%s metri</item> + </plurals> + <string name="tts_one_mile">viena jÅ«dze</string> + <plurals name="tts_miles"> + <item quantity="zero">%s mile</item> + <item quantity="one">%s jÅ«dze</item> + <item quantity="other">%s jÅ«dzes</item> + </plurals> + <string name="tts_one_foot">viena pÄ“da</string> + <plurals name="tts_feet"> + <item quantity="zero">%s pÄ“da</item> + <item quantity="one">%s pÄ“da</item> + <item quantity="other">%s pÄ“das</item> + </plurals> + <string name="tts_one_oclock">one o\'clock</string> + <string name="tts_oclock">%s o\'clock</string> + <string name="clipboard_copy_ok">IekopÄ“ts starpliktuvÄ“</string> + <plurals name="days_ago"> + <item quantity="zero">%d tikko</item> + <item quantity="one">vakar</item> + <item quantity="other">pirms %d dienÄm</item> + </plurals> + <plurals name="favorite_points"> + <item quantity="zero">%s izlases</item> + <item quantity="one">%s izlases</item> + <item quantity="other">%s izlases</item> + </plurals> + <string name="cgeo_shortcut">c:geo saÄ«sne</string> + <string name="create_shortcut">Izveidot saÄ«sni</string> + <string name="send">NosÅ«tÄ«t</string> + <string name="showcase_logcache_title">Tiek sÅ«tÄ«ts apmeklÄ“juma pieraksts</string> + <string name="showcase_logcache_text">Atcerieties, ka daudzas komandas ir tagad redzams pogÄs virspusÄ“. Tur jÅ«s atradÄ«siet pogu apmeklÄ“juma pieraksta nosÅ«tÄ«Å¡anai.</string> + <string name="showcase_main_title">Jaunas izvÄ“lnes</string> + <string name="showcase_main_text">c:geo tagad izvieto izvÄ“lnes elementus pogas tÄpat kÄ citas mÅ«sdienu aplikÄcijas. Daži elementi ir paslÄ“pti aiz punktotÄ simbola. Turiet nospiestu pogu, lai apskatÄ«tu tÄ aprakstu.</string> + <string name="showcase_cachelist_title">Saraksti pÄrslÄ“dzas</string> + <string name="showcase_cachelist_text">Varat pÄrslÄ“gties starp slÄ“pņu sarakstiem, noklikÅ¡Ä·inot uz saraksta nosaukuma.</string> + <string name="confirm_log_title">Neparasts pierakstÄ«Å¡anÄs tips</string> + <string name="confirm_log_message">You want to log \'%s\'. Are you sure?</string> +</resources> diff --git a/main/res/values-nb/strings.xml b/main/res/values-nb/strings.xml index b007671..bc12825 100644 --- a/main/res/values-nb/strings.xml +++ b/main/res/values-nb/strings.xml @@ -43,7 +43,7 @@ <string name="wp_stage">Steg i multicache</string> <string name="wp_puzzle">SpørsmÃ¥l til svar</string> <string name="wp_pkg">Parkeringsplass</string> - <string name="wp_trailhead">Startpunkt</string> + <string name="wp_trailhead">Stistart</string> <string name="wp_waypoint">Referansepunkt</string> <string name="wp_original">Opprinnelige koordinater</string> <string name="log_found">Funnet</string> @@ -74,12 +74,14 @@ <string name="log_tb_visit">Besøkte</string> <string name="log_tb_drop">Legg igjen</string> <string name="log_tb_changeall">Endre alle</string> - <string name="log_save">Lagre</string> + <string name="log_save">Lagre offline</string> <string name="log_saving">Lagrer logg…</string> <string name="log_saving_and_uploading">Sender logg og laster opp bilde…</string> <string name="log_clear">Tøm</string> <string name="log_post_not_possible">Laster loggsiden…</string> + <string name="log_date_future_not_allowed">Fremtidige loggdatoer er ikke tillatt.</string> <string name="log_add">Legg til</string> + <string name="log_repeat">Gjenta siste logg</string> <string name="log_no_rating">Ingen rangering</string> <string name="log_stars_1_description">DÃ¥rlig</string> <string name="log_stars_15_description">Ganske dÃ¥rlig</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Passord for logg:</string> <string name="log_hint_log_password">Angi passordet for logg</string> <string name="log_oc_team_comment">Kommentar fra OC-teamet</string> + <string name="log_your_saved_log">Din lagrede logg</string> <string-array name="log_image_scales"> <item>Ingen skalering</item> <item>512 px</item> @@ -122,12 +125,13 @@ <string name="err_server">Klarte ikke Ã¥ koble til Geocaching.com (server eller tilkobling nede?)</string> <string name="err_server_ec">FÃ¥r ikke kontakt med Extremcaching.com. Nettstedet kan være nede eller Internettilkoblingen fungerer ikke.</string> <string name="err_login">Ingen innloggingsopplysninger lagret</string> - <string name="err_login_failed_toast">c:geo kan ikke logge inn. c:geo fungerer frakoblet med lagrede cacher. Sjekk innloggingsinnstillinger eller aktiver Internettforbindelsen.</string> + <string name="err_login_failed_toast">c:geo kan ikke logge inn. c:geo fungerer offline med cacher du har lagret. Sjekk innloggingsinnstillinger eller aktiver internettforbindelsen.</string> <string name="err_unknown">Ukjent feil</string> + <string name="err_unknown_address">c:geo klarte ikke finne et sted ut fra denne adressen</string> <string name="err_comm">Ukjent tilkoblingsfeil</string> <string name="err_missing_auth">Brukernavn eller passord er ikke oppgitt.</string> <string name="err_wrong">Feilaktige innloggingsopplysninger</string> - <string name="err_maintenance">Geocaching.com er nede for vedlikehold. c:geo arbeider frakoblet med lagrede cacher.</string> + <string name="err_maintenance">Geocaching.com er nede for vedlikehold. c:geo arbeider offline med lagrede cacher.</string> <string name="err_license">Brukeren har ikke akseptert Geocaching.com sin lisens. c:geo kan ikke laste cachens koordinater.</string> <string name="err_unvalidated_account">Du mÃ¥ aktivere kontoen din pÃ¥ Geocaching.com først.</string> <string name="err_unpublished">Den forespurte cachen er ikke publisert.</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Henting av bilde mislyktes.</string> <string name="err_tb_display">\"Beklager, c:geo klarte ikke Ã¥ finne den sporbare du etterspurte. Er det virkelig en sporbar (trackable)?</string> <string name="err_tb_details_open">Beklager, c:geo klarte ikke Ã¥ Ã¥pne detaljerene til den sporbare.</string> - <string name="err_tb_forgot_saw">Beklager, c:geo glemte hvilken sporbare du oppdaget.</string> <string name="err_tb_find">Beklager, c:geo klarte ikke Ã¥ finne noen sporbare</string> <string name="err_tb_find_that">Beklager, c:geo finner ikke den sporbare.</string> <string name="err_waypoint_cache_unknown">c:geo vet ikke hvilken cache du vil legge til et veipunkt for.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo finner ikke din posisjon.</string> <string name="err_point_no_position_given_title">info kreves</string> <string name="err_point_no_position_given">Skriv inn minst breddegrad og lengdegrad eller avstand og peiling. Du kan ogsÃ¥ skrive inn i alle fire felt.</string> - <string name="err_point_curr_position_unavailable">c:geo har fortsatt ikke riktige koordinater. Vennligst vent…</string> <string name="err_point_bear_and_dist_title">Trenger du hjelp?</string> <string name="err_point_bear_and_dist">Skriv inn bÃ¥de retning og avstand. Retning er 0 til 360 grader i forhold til nord. Avstand angis med eller uten enheter.</string> <string name="err_log_load_data">Beklager, c:geo klarte ikke Ã¥ laste den nødvendige informasjonen for Ã¥ logge funnet.</string> <string name="err_log_load_data_again">Beklager, c:geo klarte ikke Ã¥ laste den nødvendige informasjonen for Ã¥ logge funnet. c:geo prøver pÃ¥ nytt.</string> <string name="err_log_load_data_still">c:geo laster fortsatt informasjonen som er nødvendig for Ã¥ logge funnet. Vennligst vent.</string> - <string name="err_log_post_failed">Beklager, c:geo klarte ikke Ã¥ logge funnet.</string> - <string name="err_log_post_failed_ec">Din logg ble trolig ikke lastet opp. Du bør sjekke det pÃ¥ Extremcaching.com.</string> - <string name="err_logimage_post_failed">Bildet til loggen ble trolig ikke lastet opp. Du bør sjekke det pÃ¥ Geocaching.com.</string> + <string name="err_log_post_failed">Det ser ut som loggen din ikke ble registrert. Du bør sjekke dette pÃ¥ cachens nettside.</string> + <string name="err_logimage_post_failed">Det ser ut som loggbildet ditt ikke ble lastet opp. Du bør sjekke om dette er tilfelle pÃ¥ cachens nettside.</string> <string name="err_search_address_forgot">Beklager, c:geo glemte adressen du prøvde Ã¥ finne.</string> <string name="err_parse_lat">Beklager, c:geo klarte ikke Ã¥ lese breddegraden.</string> <string name="err_parse_lon">Beklager, c:geo klarte ikke Ã¥ lese lengdegraden.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Nettverk</string> <string name="loc_fused">Kombinert</string> <string name="loc_low_power">Lavt strømforbruk</string> + <string name="loc_home">Hjemkoordinater</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Satellitter</string> <string name="loc_trying">Prøver Ã¥ lokalisere</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">I nærheten</string> <string name="advanced_search_button">Søk</string> <string name="stored_caches_button">Lagret</string> - <string name="any_button">Finn</string> + <string name="any_button">GÃ¥ til</string> <string name="unknown_scan">Fant ingen GC-koder i det skannede bildet.</string> <string name="caches_no_cache">ingen cacher</string> <string name="caches_more_caches">flere cacher</string> @@ -263,15 +265,22 @@ <string name="caches_sort_finds">Antall funn</string> <string name="caches_sort_state">Status</string> <string name="caches_sort_storage">Dato lagret i c:geo</string> + <string name="caches_sort_eventdate">Eventdato</string> <string name="caches_select_mode">Velge-modus</string> <string name="caches_select_mode_exit">Avslutt velge-modus</string> <string name="caches_select_invert">Inverter merking</string> <string name="caches_nearby">I nærheten</string> <string name="caches_manage">Administrer</string> <string name="caches_remove_all">Fjern alle</string> - <string name="caches_remove_all_confirm">Vil du fjerne alle %s cacher fra gjeldende liste?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Vil du fjerne denne cachen fra listen?</item> + <item quantity="other">Vil du fjerne alle %d cachene fra listen din?</item> + </plurals> <string name="caches_remove_selected">Fjern valgte</string> - <string name="caches_remove_selected_confirm">Vil du slette de %s merkede cachene fra enheten?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Vil du fjerne denne cachen fra enheten?</item> + <item quantity="other">Vil du slette de %d valgte cachene fra enheten?</item> + </plurals> <string name="caches_remove_progress">Fjerner cacher</string> <string name="caches_delete_events">Slett gamle eventer</string> <string name="caches_refresh_selected">Oppdater valgte</string> @@ -285,19 +294,24 @@ <string name="caches_recaptcha_hint">Tekst fra bilde</string> <string name="caches_recaptcha_continue">Fortsett</string> <string name="caches_filter">Filter</string> - <string name="caches_filter_title">Filtrer etter</string> + <string name="caches_filter_title">Filter</string> <string name="caches_filter_size">Størrelse</string> <string name="caches_filter_type">Type</string> <string name="caches_filter_track">Med sporbare</string> <string name="caches_filter_clear">Nullstill filtre</string> <string name="caches_filter_modified">Med endrede koordinater</string> + <string name="caches_filter_offline_log">Med offlinelogg</string> <string name="caches_filter_origin">Opprinnelig posisjon</string> <string name="caches_filter_distance">Avstand</string> <string name="caches_filter_personal_note">Med personlig notat</string> <string name="caches_filter_popularity">Favoritter</string> <string name="caches_filter_popularity_ratio">Favoritter [%]</string> + <string name="caches_filter_personal_data">Med personlige data</string> + <string name="caches_filter_rating">Med vurdering</string> + <string name="caches_filter_own_rating">Med egen vurdering</string> <string name="caches_removing_from_history">Fjerner fra historikken…</string> <string name="caches_clear_offlinelogs">Fjern offline-logger</string> + <string name="caches_clear_offlinelogs_message">Vil du fjerne offline-loggene?</string> <string name="caches_clear_offlinelogs_progress">Fjerner offline-logger</string> <string name="list_menu_create">Opprett ny liste</string> <string name="list_menu_drop">Fjern liste</string> @@ -320,13 +334,17 @@ <string name="list_not_available">Listen er ikke lenger tilgjengelig, bytter til standarlisten</string> <string name="about_version">Versjon</string> <string name="about_changelog">Oppdateringslogg</string> + <string name="about_system">System</string> <string name="about_donate">Donér</string> <string name="about_donation_more">Donér til\nutviklerne</string> <string name="about_contributors">Bidragsytere</string> <string name="about_license">Lisens</string> <string name="about_apache_license"><a href="">Apache-lisens, versjon 2.0</a></string> <string name="about_help">Hjelp</string> + <string name="about_system_include">Inkluder den følgende informasjonen nÃ¥r du sender en feilrapport eller ber om mer informasjon fra c:geo:</string> + <string name="changelog_github">Liste over alle endringer</string> <string name="settings_title_services">Tjenester</string> + <string name="settings_summary_services">Konfigurer kontoinformasjon og tilgang til tilleggstjenester.</string> <string name="settings_title_appearance">Utseende</string> <string name="settings_title_cachedetails">Cache-detaljer</string> <string name="settings_title_offlinedata">Offline-data</string> @@ -334,14 +352,17 @@ <string name="settings_title_map">Vis pÃ¥ kartet</string> <string name="settings_title_map_data">Kartdata</string> <string name="settings_title_map_content">Kartinnhold</string> + <string name="settings_title_gpx">GPX</string> <string name="settings_title_basicmembers">Alternativer for Basic-medlemmer</string> <string name="settings_title_navigation">Navigasjon</string> <string name="settings_title_system">System</string> <string name="settings_title_navigation_menu">Navigasjonsmenyen</string> <string name="settings_category_browser">Nettleser</string> + <string name="settings_category_geocaching">Geocaching</string> <string name="settings_category_social">Sosiale medier</string> <string name="settings_category_logging_other">Andre loggeinnstillinger</string> <string name="settings_goto_url_button">mer…</string> + <string name="settings_title_gc">Geocaching.com</string> <string name="settings_title_ec">Extremcaching.com</string> <string name="settings_title_ox">Opencaching.com (Garmin)</string> <string name="settings_activate_gc">Aktiver</string> @@ -355,17 +376,25 @@ <string name="init_oc">Opencaching.de</string> <string name="settings_activate_oc">Aktiver</string> <string name="init_oc_de_description">Gi c:geo tilgang til Ã¥ bruke opencaching.de for Ã¥ søke etter cacher og vise/filtrere dine funnede cacher.</string> + <string name="init_oc_pl">Opencaching.pl</string> <string name="settings_activate_oc_pl">Aktiver</string> <string name="init_oc_pl_description">Gi c:geo tilgang til Ã¥ bruke opencaching.pl for Ã¥ søke etter cacher og vise/filtrere dine funnede cacher.</string> + <string name="init_oc_nl">Opencaching.nl</string> <string name="settings_activate_oc_nl">Aktiver</string> <string name="init_oc_nl_description">Gi c:geo tilgang til Ã¥ bruke opencaching.nl for Ã¥ søke etter cacher og vise/filtrere dine funnede cacher.</string> + <string name="init_oc_us">Opencaching.us</string> <string name="settings_activate_oc_us">Aktiver</string> <string name="init_oc_us_description">Gi c:geo tilgang til Ã¥ bruke opencaching.us for Ã¥ søke etter cacher og vise/filtrere dine funnede cacher.</string> + <string name="init_oc_ro">Opencaching.ro</string> <string name="settings_activate_oc_ro">Aktiver</string> <string name="init_oc_ro_description">Gi c:geo tilgang til Ã¥ bruke opencaching.ro for Ã¥ søke etter cacher og vise/filtrere dine funnede cacher.</string> + <string name="init_oc_uk">Opencaching.org.uk</string> <string name="settings_activate_oc_uk">Aktiver</string> <string name="init_oc_uk_description">Gi c:geo tilgang til Ã¥ bruke opencaching.org.uk for Ã¥ søke etter cacher og vise/filtrere dine funnede cacher.</string> <string name="init_gcvote">GCVote.com</string> + <string name="init_gcvote_password_description">For Ã¥ kunne vurdere en cache mÃ¥ du følge instruksjonene pÃ¥ GCVote.com og angi ditt GCVote passord her.</string> + <string name="err_gcvote_send_rating">Feil ved sending av vurdering. Sjekk at passordet for GCVote i innstillingene er riktig eller fjern passordet.</string> + <string name="gcvote_sent">Stemmegivning sendt</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktiver</string> <string name="init_username">Brukernavn</string> @@ -436,6 +465,8 @@ <string name="init_backup_success">Databasen til c:geo ble kopiert til:</string> <string name="init_backup_failed">Sikkerhetskopi av databasen til c:geo mislyktes.</string> <string name="init_backup_unnecessary">Databasen er tom, sikkerhetskopiering er ikke nødvendig.</string> + <string name="backup_confirm_overwrite">Vil du overskrive den eksisterende sikkerhetskopien fra %s?</string> + <string name="restore_confirm_overwrite">Vil du overskrive %s pÃ¥ enheten din med sikkerhetskopien?</string> <string name="init_restore_success">Gjenoppretting fullført.</string> <string name="init_restore_failed">Gjenoppretting mislyktes.</string> <string name="init_restore_running">Gjenoppretter databasen…</string> @@ -485,10 +516,17 @@ <string name="init_maintenance_directories_note">c:geo lagrer bilder, loggbilder og andre filer knyttet til en cache i en egen mappe. I noen situasjoner (som importering/eksportering av databasen) vil denne mappen inneholde utdaterte filer som kan slettes her.</string> <string name="init_maintenance_directories">Slett utdaterte filer</string> <string name="init_location">Geolokasjon</string> + <string name="init_location_note">PÃ¥ enheter utstyrt med Google spill tjenester, kan c:geo automatisk bruke en bedre geolocation-leverandør. Men dette forhindrer bruk av en ekstern BlueTooth GPS-mottaker.</string> <string name="init_location_googleplayservices">Bruk Google Play Services</string> + <string name="init_low_power">Strømsparingsmodus</string> + <string name="init_low_power_note">Strømsparingsmodus unngÃ¥r GPS og gyroskop nÃ¥r en svært nøyaktig plassering ikke er strengt nødvendig, men det gir lengere behandlingstid.</string> + <string name="init_low_power_mode">Aktivere strømsparingsmodus</string> <string name="init_create_memory_dump">Opprett minnedump</string> <string name="init_memory_dump">Minnedump</string> <string name="init_memory_dumped">Minne dumpet til %s</string> + <string name="init_hardware_acceleration_title">Maskinvareakselerert rendering</string> + <string name="init_hardware_acceleration_note">Maskinvare-akselerasjon gjengir grafikkelementer raskere pÃ¥ skjermen. Men pÃ¥ noen Android telefoners operativsystem er det noen feil, og noe av teksten kan komme fram som uklare Deaktiver maskinvare-akselerasjonen hvis dette skjer med deg.</string> + <string name="init_hardware_acceleration">Aktivere maskinvareakselerasjonen</string> <string name="settings_open_website">Ã…pne nettside</string> <string name="settings_settings">Innstillinger</string> <string name="settings_information">Informasjon</string> @@ -536,7 +574,7 @@ <string name="auth_ocde">opencaching.de</string> <string name="auth_dialog_completed_oc">c:geo har nÃ¥ fÃ¥tt godkjenning til Ã¥ kommunisere med %s.</string> <plurals name="cache_counts"> - <item quantity="one">Én cache</item> + <item quantity="one">En cache</item> <item quantity="other">%1$d cacher</item> </plurals> <string name="cache_offline">Offline</string> @@ -581,11 +619,12 @@ <string name="cache_images">Bilder</string> <string name="cache_waypoints">Veipunkter</string> <plurals name="waypoints"> - <item quantity="one">1 veipunkt</item> + <item quantity="one">Et veipunkt</item> <item quantity="other">%d veipunkter</item> </plurals> <string name="cache_waypoints_add">Legg til veipunkter</string> <string name="cache_hint">Hint</string> + <string name="cache_hint_not_available">Ingen hint tilgjengelig</string> <string name="cache_logs">Loggbok</string> <string name="cache_logs_friends_and_own">Venners/egne logger</string> <string name="cache_dialog_loading_details">Laster cachens detaljer…</string> @@ -625,9 +664,10 @@ <string name="cache_menu_streetview">Gatevisning</string> <string name="cache_menu_browser">Ã…pne i nettleseren</string> <string name="cache_menu_visit">Logg funn</string> - <string name="cache_menu_visit_offline">Logg besøket offline</string> + <string name="cache_menu_visit_offline">Ett-klikks offlinelogg</string> <string name="cache_menu_spoilers">Bilder</string> <string name="cache_menu_around">Cacher i nærheten</string> + <string name="around">Rundt %s</string> <string name="cache_menu_event">Eksporter til kalender</string> <string name="cache_menu_details">Detaljer</string> <string name="cache_menu_refresh">Oppdater</string> @@ -636,6 +676,9 @@ <string name="cache_menu_whereyougo">WhereYouGo</string> <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">Avgi stemme</string> + <string name="cache_menu_checker">Ã…pne Geochecker</string> + <string name="cache_menu_ignore">Ignorer cache</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Logg lagret</string> <string name="cache_status_found">Funnet</string> @@ -721,6 +764,7 @@ <string name="waypoint_note">Note</string> <string name="waypoint_visited">Besøkte</string> <string name="waypoint_save">Save</string> + <string name="waypoint_cancel_edit">Avbryt</string> <string name="waypoint_loading">Laster veipunkt…</string> <string name="waypoint_do_not_touch_cache_coordinates">Ingen endring i cachens koordinater</string> <string name="waypoint_set_as_cache_coords">Angi som cachens koordinater i c:geo</string> @@ -745,6 +789,8 @@ <string name="search_clear_history">Slett historikk</string> <string name="search_history_cleared">Historikken er slettet</string> <string name="waypoint_coordinate_formats_plain">Ren tekst</string> + <string name="from_clipboard">Fra utklippstavlen.</string> + <string name="copy_to_clipboard">Kopier til utklippstavle</string> <string name="visit_tweet">Del dette funnet pÃ¥ Twitter</string> <string name="map_map">Kart</string> <string name="map_live">Live-kart</string> @@ -776,7 +822,7 @@ <string name="search_address_button">Søk med adresse</string> <string name="search_geo">Geokode</string> <string name="search_geo_button">Søk med geokode</string> - <string name="search_kw">Nøkklord</string> + <string name="search_kw">Nøkkelord</string> <string name="search_kw_prefill">Nøkkelord</string> <string name="search_kw_button">Søk med nøkkelord</string> <string name="search_fbu">Funnet av bruker</string> @@ -786,7 +832,7 @@ <string name="search_hbu_prefill">Eier</string> <string name="search_hbu_button">Søk med</string> <string name="search_tb">Sporbar (trackable)</string> - <string name="search_tb_hint">Identifisering av sporbare</string> + <string name="search_tb_hint">Sporingskode</string> <string name="search_tb_button">Søk etter sporbare</string> <string name="search_destination">Lokaliser ved hjelp av koordinater</string> <string name="search_direction_rel">Fra denne plassen</string> @@ -796,7 +842,7 @@ <string name="search_pocket_title">Pocket Query</string> <string name="search_pocket_loading">Laster en liste med Pocket Queries</string> <string name="search_pocket_select">Velg Pocket Query</string> - <string name="trackable">Sporbar</string> + <string name="trackable">Sporbar (TB eller coin)</string> <string name="trackable_details_loading">Laster detaljene til den sporbare…</string> <string name="trackable_log_touch">Logg sporbar</string> <string name="trackable_browser_open">Ã…pne i nettleseren</string> @@ -849,7 +895,7 @@ <string name="helper_contacts_description">Gjør det mulig Ã¥ Ã¥pne en kontakt (i telefonens adressebok) direkte fra en logg sÃ¥ du enklere kan be om hjelp fra dine venner.</string> <string name="helper_sendtocgeo_description">Send til c:geo (send2c:geo) er en nettleserutvidelse <strong>for din pc</strong>. PÃ¥ geocaching.com kan du sende cacher til din smarttelefon ved hjelp av en egen knapp i nettleseren.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Enkel, brukervennlig app for Ã¥ vise online kart, men som ogsÃ¥ kan laste ned kart til offline bruk. Støtter ogsÃ¥ spor, POI-hÃ¥ndtering (points of interest) og mange andre nyttige funksjoner.</string> + <string name="helper_locus_description">App for utendørs navigasjon til din mobil eller tablet. I appen kan du se topo-kart offline, spore ruten din, lete etter turbokser, bruke en stemmeguide og mye annet.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Du kan bruke radaren i denne appen sammen med c:geo. Den gir mye GPS-relatert informasjon.</string> <string name="helper_bluetoothgps_title">BlÃ¥tann-GPS</string> @@ -1101,12 +1147,15 @@ <string name="attribute_offset_cache_no">Ikke offset-cache</string> <string name="quote">For Ã¥ gjøre geocaching enklere og brukerne latere.</string> <string name="powered_by">carnero</string> - <string name="support">e-post adresse: <a href="mailto:support@cgeo.org">support@cgeo.org</a></string> - <string name="website">web-side: <a href="http://cgeo.org/">cgeo.org</a></string> - <string name="facebook">facebook: <a href="http://www.facebook.com/pages/cgeo/297269860090">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo i Google Play</a></string> + <string name="support_title">Støtte</string> + <string name="website_title">Nettside</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href=""> c:geo-siden</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo i Google Play</a></string> <string name="about_twitter">Ønsker du at <b>c:geo</b> skal poste en status pÃ¥ Twitter hver gang du logger ett funn via <b>c:geo</b>?</string> + <string name="faq_title">Ofte Stilte SpørsmÃ¥l</string> <string name="status_new_release" tools:ignore="UnusedResources">Ny versjon tilgjengelig. \nKlikk for Ã¥ installere.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Ny \"nightly build\" er tilgjengelig.\nKlikk for Ã¥ installere.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Ny \"release candidate\" er tilgjengelig.\nKlikk for Ã¥ installere.</string> @@ -1141,9 +1190,9 @@ </plurals> <plurals name="favorite_points"> <item quantity="one">%s favoritt</item> - <item quantity="other">%s favoritt</item> + <item quantity="other">%s favoritter</item> </plurals> - <string name="percent_favorite_points">%\ favoritter</string> + <string name="more_than_percent_favorite_points">> %d%% favoritter.</string> <string name="cgeo_shortcut">c:geo-snartvei</string> <string name="create_shortcut">Opprett snarvei</string> <string name="send">Send</string> @@ -1151,6 +1200,10 @@ <string name="showcase_logcache_text">Husk, mange kommandoer er nÃ¥ i tittellinjen. Der finner du knappen for Ã¥ sende den ferdige loggen.</string> <string name="showcase_main_title">Nye menyer</string> <string name="showcase_main_text">c:geo har nÃ¥ plassert menyelementer i tittellinjen, slik som andre moderne app-er. Noen elementer er skjult bak symbolet med prikker. Langt trykk pÃ¥ en knapp viser en beskrivelse av funksjonen.</string> + <string name="showcase_cachelist_title">Bytter lister.</string> + <string name="showcase_cachelist_text">Du kan bytte mellom geocache lister ved Ã¥ klikke pÃ¥ tittelen pÃ¥ listen.</string> + <string name="showcase_compass_hint_title">Vis hint</string> + <string name="showcase_compass_hint_text">Denne nye menyen kan gi deg hjelp til Ã¥ finne cachen - her vises hintet, hvis det er tilgjengelig.</string> <string name="confirm_log_title">Uvanlig loggtype</string> <string name="confirm_log_message">Du vil logge \'%s\'. Er du sikker?</string> </resources> diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml index 76efe6a..60a4243 100644 --- a/main/res/values-nl/strings.xml +++ b/main/res/values-nl/strings.xml @@ -41,7 +41,7 @@ <string name="cache_size_very_large">Erg Groot</string> <string name="wp_final">Eindbestemming</string> <string name="wp_stage">Multi-cache punt</string> - <string name="wp_puzzle">Vraag voor antwoord</string> + <string name="wp_puzzle">Te beantwoorden vraag</string> <string name="wp_pkg">Parkeer gelegenheid</string> <string name="wp_trailhead">Trailhead</string> <string name="wp_waypoint">Referentie punt</string> @@ -74,12 +74,14 @@ <string name="log_tb_visit">Bezoek</string> <string name="log_tb_drop">Hier droppen</string> <string name="log_tb_changeall">Wijzig alles</string> - <string name="log_save">Opslaan</string> + <string name="log_save">Off line opslaan</string> <string name="log_saving">Log opslaan…</string> <string name="log_saving_and_uploading">Verzenden van log en uploaden foto…</string> <string name="log_clear">Wissen</string> <string name="log_post_not_possible">Laden Log Pagina…</string> + <string name="log_date_future_not_allowed">Log datums in de toekomst zijn niet toegestaan.</string> <string name="log_add">Toevoegen</string> + <string name="log_repeat">Herhaal laatste log</string> <string name="log_no_rating">Geen beoordeling</string> <string name="log_stars_1_description">Slecht</string> <string name="log_stars_15_description">Redelijk slecht</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Log wachtwoord:</string> <string name="log_hint_log_password">Voer Login Wachtwoord</string> <string name="log_oc_team_comment">OC Team commentaar</string> + <string name="log_your_saved_log">Je opgeslagen log</string> <string-array name="log_image_scales"> <item>Niet schalen</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Geen login informatie opgeslagen</string> <string name="err_login_failed_toast">Sorry, c:geo kan niet inloggen. c:geo werkt in offline modus. Controleer je gebruikersnaam en wachtwoord en/of zet de internetverbinding aan.</string> <string name="err_unknown">Onbekende fout</string> + <string name="err_unknown_address">c:geo was niet in staat dit adres te herkennen als bestaande locatie</string> <string name="err_comm">Onbekende communicatiefout</string> <string name="err_missing_auth">Geen gebruikersnaam en/of wachtwoord ingesteld.</string> <string name="err_wrong">Foutieve login informatie</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Verwerven van een foto is mislukt.</string> <string name="err_tb_display">Sorry, c:geo kan de gezochte trackable niet weergeven. Is het wel een trackable?</string> <string name="err_tb_details_open">Sorry, c:geo kan de trackable details niet laden.</string> - <string name="err_tb_forgot_saw">Sorry, c:geo is vergeten welke trackable je gezien hebt.</string> <string name="err_tb_find">Sorry, c:geo kan de trackable niet vinden</string> <string name="err_tb_find_that">Sorry, c:geo kan die trackable niet vinden.</string> <string name="err_waypoint_cache_unknown">Sorry, c:geo weet niet aan welke cache je een waypoint wil toevoegen.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">Sorry, c:geo kan niet bepalen waar je bent.</string> <string name="err_point_no_position_given_title">Info benodigd</string> <string name="err_point_no_position_given">Geef op zijn minst lengte- en breedtegraad of afstand en richting. Of vul alle 4 de velden.</string> - <string name="err_point_curr_position_unavailable">c:geo heeft de huidige coördinaten nog niet. Even geduld a.u.b….</string> <string name="err_point_bear_and_dist_title">Hulp nodig?</string> <string name="err_point_bear_and_dist">Vul zowel richting als afstand. Richting is hoek van 0 to 360 graden t.o.v. het noorden. Afstand mag met of zonder eenheid.</string> <string name="err_log_load_data">Sorry, c:geo kan data om bezoek te loggen niet laden.</string> <string name="err_log_load_data_again">Sorry, c:geo kan data om bezoek te loggen niet laden. Bezig nogmaals te proberen.</string> <string name="err_log_load_data_still">c:geo is nog steeds bezig om data te laden om bezoek te loggen. Graag nog even geduld.</string> - <string name="err_log_post_failed">Sorry, het is c:geo niet gelukt het log te posten.</string> - <string name="err_log_post_failed_ec">Het lijkt erop dat uw log niet werd gepost. Controleer het op Extremcaching.com.</string> - <string name="err_logimage_post_failed">Het lijkt erop dat uw log-foto niet geüpload is. Controleer het op Geocaching.com.</string> + <string name="err_log_post_failed">Het lijkt erop dat je log niet werd gepost. Controleer het op de cache webpagina.</string> + <string name="err_logimage_post_failed">Het lijkt erop dat uw log-afbeelding niet is geüpload. Controleer het op de cache webpagina.</string> <string name="err_search_address_forgot">Sorry, c:geo is het adres dat je zoekt vergeten.</string> <string name="err_parse_lat">Sorry, c:geo kan breedtegraad niet verwerken.</string> <string name="err_parse_lon">Sorry, c:geo kan lengtegraad niet verwerken.</string> @@ -210,7 +211,8 @@ <string name="loc_last">Laatst bekende</string> <string name="loc_net">Netwerk</string> <string name="loc_fused">Gecombineerd</string> - <string name="loc_low_power">Batterij bijna leeg</string> + <string name="loc_low_power">Spaarstand</string> + <string name="loc_home">Thuis coördinaten</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Proberen te lokaliseren</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Dichtbij</string> <string name="advanced_search_button">Zoeken</string> <string name="stored_caches_button">Opgeslagen</string> - <string name="any_button">Elke locatie</string> + <string name="any_button">Ga naar</string> <string name="unknown_scan">De gescande afbeelding bevat geen geocode.</string> <string name="caches_no_cache">Geen caches</string> <string name="caches_more_caches">Meer caches</string> @@ -263,15 +265,14 @@ <string name="caches_sort_finds">Aantal keer gevonden</string> <string name="caches_sort_state">Selectie omkeren</string> <string name="caches_sort_storage">Datum opgeslagen op apparaat</string> + <string name="caches_sort_eventdate">Event datum</string> <string name="caches_select_mode">Selectie modus</string> <string name="caches_select_mode_exit">Selectie modus beëindigen</string> <string name="caches_select_invert">Selectie omkeren</string> <string name="caches_nearby">Nabij</string> <string name="caches_manage">Beheer</string> <string name="caches_remove_all">Verwijder alles</string> - <string name="caches_remove_all_confirm">Wil je alle %s caches uit de huidige lijst verwijderen?</string> <string name="caches_remove_selected">Selectie verwijderen</string> - <string name="caches_remove_selected_confirm">Wil je de geselecteerde %s caches verwijderen van uw apparaat?</string> <string name="caches_remove_progress">Caches worden verwijderd</string> <string name="caches_delete_events">Verwijder afgelopen evenementen</string> <string name="caches_refresh_selected">Ververs geselecteerden</string> @@ -291,13 +292,18 @@ <string name="caches_filter_track">Met trackables</string> <string name="caches_filter_clear">Maak filters leeg</string> <string name="caches_filter_modified">Met aangepaste coordinaten</string> + <string name="caches_filter_offline_log">Met offline log</string> <string name="caches_filter_origin">Oorsprong</string> <string name="caches_filter_distance">Afstand</string> <string name="caches_filter_personal_note">Met privé cachenotitie</string> <string name="caches_filter_popularity">Favorieten</string> <string name="caches_filter_popularity_ratio">Favorieten [%]</string> + <string name="caches_filter_personal_data">Met persoonlijke gegevens</string> + <string name="caches_filter_rating">Met rating</string> + <string name="caches_filter_own_rating">Met eigen rating</string> <string name="caches_removing_from_history">Verwijderen uit geschiedenis…</string> <string name="caches_clear_offlinelogs">Verwijderen offline logs</string> + <string name="caches_clear_offlinelogs_message">Wil je de offline logs wissen?</string> <string name="caches_clear_offlinelogs_progress">Offline logs worden verwijderd</string> <string name="list_menu_create">Maak nieuwe lijst</string> <string name="list_menu_drop">Verwijder huidige lijst</string> @@ -320,13 +326,17 @@ <string name="list_not_available">Lijst is niet langer beschikbaar, wissel naar standaard lijst</string> <string name="about_version">Versie</string> <string name="about_changelog">Changelog</string> + <string name="about_system">Systeem</string> <string name="about_donate">Doneren</string> <string name="about_donation_more">Doneren aan\nontwikkeling</string> <string name="about_contributors">Bijdragers</string> <string name="about_license">Licentie</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Help</string> + <string name="about_system_include">Voeg volgende systeem informatie toe wanneer je een bug report stuurt of vraagt om meer informatie over c:geo:</string> + <string name="changelog_github">Lijst met alle wijzigingen</string> <string name="settings_title_services">Diensten</string> + <string name="settings_summary_services">Gebruikersaccount informatie en toegang tot optionele services configureren.</string> <string name="settings_title_appearance">Uiterlijk</string> <string name="settings_title_cachedetails">Cache Details</string> <string name="settings_title_offlinedata">Offline gegevens</string> @@ -374,6 +384,9 @@ <string name="settings_activate_oc_uk">Activeren</string> <string name="init_oc_uk_description">c:geo authoriseren met opencaching.org.uk om naar caches te zoeken en het filteren van gevonden caches.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Om een cache te kunnen beoordelen, volg de instructies op GCVote.com en geef hier uw GCVote wachtwoord op.</string> + <string name="err_gcvote_send_rating">Fout bij het verzenden van beoordeling, controleer het GCVote wachtwoord in instellingen of maak deze leeg.</string> + <string name="gcvote_sent">Stem succesvol verzonden</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activeren</string> <string name="init_username">Gebruikersnaam</string> @@ -444,6 +457,8 @@ <string name="init_backup_success">De database van c:geo was succesvol gekopieerd naar het bestand:</string> <string name="init_backup_failed">Backup van c:geo database is niet gelukt.</string> <string name="init_backup_unnecessary">Database is leeg, backup niet nodig.</string> + <string name="backup_confirm_overwrite">Wilt je de bestaande backup van %s overschrijven?</string> + <string name="restore_confirm_overwrite">Wil je %s op uw apparaat overschrijven met de backup?</string> <string name="init_restore_success">Herstellen is gelukt.</string> <string name="init_restore_failed">Herstellen is niet gelukt.</string> <string name="init_restore_running">Herstellen van de cache database…</string> @@ -583,7 +598,7 @@ <string name="cache_personal_note_upload">Uploaden</string> <string name="cache_personal_note_uploading">Uploading persoonlijke notitie</string> <string name="cache_personal_note_upload_done">Persoonlijke notitie geupload</string> - <string name="cache_personal_note_upload_cancelled">Persoonlijk notitie uploaden geannulleerd</string> + <string name="cache_personal_note_upload_cancelled">Persoonlijke notitie uploaden geannuleerd</string> <string name="cache_description">Omschrijving</string> <string name="cache_description_long">Lange omschrijving</string> <string name="cache_description_table_note">Omschrijving bevat een tabel-layout welke misschien op %s bekeken moet worden.</string> @@ -606,6 +621,7 @@ </plurals> <string name="cache_waypoints_add">Waypoint toevoegen</string> <string name="cache_hint">Hint</string> + <string name="cache_hint_not_available">Geen hint beschikbaar</string> <string name="cache_logs">Logboek</string> <string name="cache_logs_friends_and_own">Vrienden/Eigen Logs</string> <string name="cache_dialog_loading_details">Cache details laden…</string> @@ -645,9 +661,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Open in browser</string> <string name="cache_menu_visit">Log bezoek</string> - <string name="cache_menu_visit_offline">Log bezoek offline</string> + <string name="cache_menu_visit_offline">Enkele klik offline log</string> <string name="cache_menu_spoilers">Spoiler afbeeldingen</string> <string name="cache_menu_around">Caches rondom</string> + <string name="around">Rondom %s</string> <string name="cache_menu_event">Toevoegen aan kalender</string> <string name="cache_menu_details">Details</string> <string name="cache_menu_refresh">Verversen</string> @@ -657,6 +674,10 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_android_wear">Android Wear</string> + <string name="cache_menu_vote">Stem</string> + <string name="cache_menu_checker">Open Geochecker</string> + <string name="cache_menu_ignore">Negeer cache</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Log opgeslagen</string> <string name="cache_status_found">Gevonden</string> @@ -742,6 +763,7 @@ <string name="waypoint_note">Notitie</string> <string name="waypoint_visited">Bezocht</string> <string name="waypoint_save">Opslaan</string> + <string name="waypoint_cancel_edit">Annuleren</string> <string name="waypoint_loading">Waypoint laden…</string> <string name="waypoint_do_not_touch_cache_coordinates">Wijzig cachecoördinaten niet</string> <string name="waypoint_set_as_cache_coords">Zet als cachecoördinaten in c:geo</string> @@ -766,6 +788,8 @@ <string name="search_clear_history">Maak geschiedenis leeg</string> <string name="search_history_cleared">Geschiedenis leeggemaakt</string> <string name="waypoint_coordinate_formats_plain">Plat</string> + <string name="from_clipboard">Van klembord</string> + <string name="copy_to_clipboard">Kopieer naar klembord</string> <string name="visit_tweet">Post deze vondst op Twitter</string> <string name="map_map">Kaart</string> <string name="map_live">Live kaart</string> @@ -870,7 +894,7 @@ <string name="helper_contacts_description">Maakt het mogelijk een contactpersoon (uit je adresboek) te openen rechtstreeks vanuit een log, zodat je vrienden makkelijker om hulp kunt vragen.</string> <string name="helper_sendtocgeo_description">Verzenden naar c:geo is een browserextensie <strong>voor uw PC</strong>. Tijdens het browsen op geocaching.com, kunt u caches verzenden naar uw smartphone met een klik direct in de browser.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Simpele bruikbare applicatie om online kaarten weer te geven en deze voor offline gebruik te downloaden (alleen rasterkarten). Ook ondersteuning voor track recording, poi afhandeling en vele andere handige functies.</string> + <string name="helper_locus_description">Outdoor navigatie app voor uw telefoon of Tablet. Topo kaarten offline bekijken, uw route vastleggen, geocaches zoeken, gebruik een stem gids en meer.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">De radar van deze applicatie kan gebruikt worden samen met c:geo. Het bied ook vele andere GPS gerelateerde informatie.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -982,7 +1006,7 @@ <string name="attribute_snowshoes_no">Geen sneeuwschoenen nodig</string> <string name="attribute_skiis_yes">Langlaufski\'s nodig</string> <string name="attribute_skiis_no">Langlaufski\'s niet nodig</string> - <string name="attribute_s_tool_yes">Speciate gereedschappen nodig</string> + <string name="attribute_s_tool_yes">Speciale gereedschappen nodig</string> <string name="attribute_s_tool_no">Geen speciale gereedschappen nodig</string> <string name="attribute_wirelessbeacon_yes">Draadloos baken</string> <string name="attribute_wirelessbeacon_no">Geen draadloos baken</string> @@ -1122,13 +1146,15 @@ <string name="attribute_offset_cache_no">Geen offset cache</string> <string name="quote">Om geocaching makkelijker en gebruikers luier te maken.</string> <string name="powered_by">carnero</string> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Website: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo op Google Play</a></string> + <string name="support_title">Ondersteuning</string> + <string name="website_title">Website</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">c:geo pagina</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo op Google Play</a></string> <string name="about_twitter">Moet <b>c:geo</b> elke cache vondst publiceren naar Twitter?</string> - <string name="faq">FAQ: <a href=""> faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Nieuwe release beschikbaar.\nTik om te installeren.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nieuwe nightly-release beschikbaar.\nTik om te installeren.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nieuwe release-candidaad beschikbaar.\nTik om te installeren.</string> @@ -1173,7 +1199,7 @@ <item quantity="one">%s favoriet</item> <item quantity="other">%s favorieten</item> </plurals> - <string name="percent_favorite_points">%\ favorieten</string> + <string name="more_than_percent_favorite_points">> %d %% favorieten</string> <string name="cgeo_shortcut">c:geo snelkoppeling</string> <string name="create_shortcut">Maak snelkoppeling</string> <string name="send">Verzenden</string> @@ -1183,6 +1209,8 @@ <string name="showcase_main_text">c:geo plaatst nu menu-items in de titelbalk, zoals veel andere moderne apps. Sommige items zijn verborgen achter het symbool met de drie puntjes. Druk lang op een knop om de beschrijving te zien.</string> <string name="showcase_cachelist_title">Wisselen van lijst</string> <string name="showcase_cachelist_text">Je kan wisselen tussen geocache lijsten door te klikken op de titel van de lijst.</string> + <string name="showcase_compass_hint_title">Toon hint</string> + <string name="showcase_compass_hint_text">Dit nieuwe menu-item kan een idee geven waar de cache gevonden kan worden - het toont de hint, indien beschikbaar.</string> <string name="confirm_log_title">Ongebruikelijk logtype</string> <string name="confirm_log_message">Je wilt \'%s\' loggen. Weet je het zeker?</string> </resources> diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml index 9c22836..de70b49 100644 --- a/main/res/values-pl/strings.xml +++ b/main/res/values-pl/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">Odwiedzony</string> <string name="log_tb_drop">OdÅ‚ożony</string> <string name="log_tb_changeall">ZmieÅ„ wszystko</string> - <string name="log_save">Zapisz</string> + <string name="log_save">Zapisz offline</string> <string name="log_saving">ZapisujÄ™ w dzienniku…</string> <string name="log_saving_and_uploading">ZapisujÄ™ w dzienniku i wysyÅ‚am zdjÄ™cie…</string> <string name="log_clear">Wyczyść</string> <string name="log_post_not_possible">ÅadujÄ™ dziennik…</string> + <string name="log_date_future_not_allowed">Wpisy z przyszÅ‚Ä… datÄ… nie sÄ… dozwolone.</string> <string name="log_add">Dodaj</string> + <string name="log_repeat">Powtórz ostatni wpis</string> <string name="log_no_rating">Bez oceny</string> <string name="log_stars_1_description">SÅ‚aba</string> <string name="log_stars_15_description">Raczej sÅ‚aba</string> @@ -107,6 +109,7 @@ <string name="log_password_title">HasÅ‚o do logu:</string> <string name="log_hint_log_password">Wpisz hasÅ‚o do logu</string> <string name="log_oc_team_comment">Komentarz zespoÅ‚u OC</string> + <string name="log_your_saved_log">Twój zapisany wpis</string> <string-array name="log_image_scales"> <item>Brak skalowania</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Brak danych do logowania.</string> <string name="err_login_failed_toast">c:geo nie może zalogować siÄ™. c:geo pracuje offline z zapisanymi skrzynkami. Sprawdź ustawienia logowania i poÅ‚Ä…czenie z internetem.</string> <string name="err_unknown">Nieznany bÅ‚Ä…d</string> + <string name="err_unknown_address">c:geo nie mógÅ‚ dopasować adresu do istniejÄ…cej lokalizacji</string> <string name="err_comm">Nieznany bÅ‚Ä…d w komunikacji</string> <string name="err_missing_auth">Brak nazwy użytkownika i/lub hasÅ‚a.</string> <string name="err_wrong">Niepoprawne dane użytkownika</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Nie można pobrać obrazu.</string> <string name="err_tb_display">c:geo nie może pokazać przedmiotów podróżnych. Czy to naprawdÄ™ jest przedmiot podróżny?</string> <string name="err_tb_details_open">c:geo nie może otworzyć szczegółów przedmiotu podróżnego.</string> - <string name="err_tb_forgot_saw">c:geo zapomiaÅ‚, który przedmiot podróżny widziaÅ‚eÅ›.</string> <string name="err_tb_find">c:geo nie może znaleźć przedmiotu podróżnego.</string> <string name="err_tb_find_that">c:geo nie może znaleźć tego przedmiotu podróżnego.</string> <string name="err_waypoint_cache_unknown">c:geo nie wie, do której skrzynki chcesz dodać punkt nawigacji.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo nie może okreÅ›lić Twojej lokalizacji.</string> <string name="err_point_no_position_given_title">Informacje wymagane</string> <string name="err_point_no_position_given">WypeÅ‚nij co najmniej szerokość i dÅ‚ugość geograficznÄ… lub odlegÅ‚ość i namiar. Możesz również wypeÅ‚nić wszystkie cztery pola.</string> - <string name="err_point_curr_position_unavailable">c:geo nadal nie zna aktualnych współrzÄ™dnych. ProszÄ™ chwilÄ™ poczekać…</string> <string name="err_point_bear_and_dist_title">Potrzebujesz pomocy?</string> <string name="err_point_bear_and_dist">WypeÅ‚nij zarówno namiar i odlegÅ‚ość. BiorÄ…c kÄ…t od 0 do 360 stopni w stosunku do północy. OdlegÅ‚ość z lub bez jednostki.</string> <string name="err_log_load_data">c:geo nie może zaÅ‚adować danych wymaganych do wpisania wizyty.</string> <string name="err_log_load_data_again">c:geo nie może zaÅ‚adować danych wymaganych do wpisania wizyty. PróbujÄ™ ponownie.</string> <string name="err_log_load_data_still">Nadal trwa Å‚adowanie danych wymaganych do wpisu w dzienniku. ProszÄ™ czekać…</string> - <string name="err_log_post_failed">WyglÄ…da na to, że Twój wpis nie zostaÅ‚ wysÅ‚any. ProszÄ™ sprawdź na Geocaching.com.</string> - <string name="err_log_post_failed_ec">WyglÄ…da na to, że Twój wpis nie zostaÅ‚ wysÅ‚any. ProszÄ™ sprawdź na Extremcaching.com.</string> - <string name="err_logimage_post_failed">WyglÄ…da na to, że Twój obraz nie zostaÅ‚ dodany. ProszÄ™ sprawdź na Geocaching.com.</string> + <string name="err_log_post_failed">WyglÄ…da na to, że wpis nie zostaÅ‚ dodany. ProszÄ™ sprawdzić to na stronie internetowej skrzynki.</string> + <string name="err_logimage_post_failed">WyglÄ…da na to, że zdjÄ™cie nie zostaÅ‚o przesÅ‚ane. ProszÄ™ sprawdzić to na stronie internetowej skrzynki.</string> <string name="err_search_address_forgot">c:geo zapomniaÅ‚ adresu, którego szukaÅ‚eÅ›.</string> <string name="err_parse_lat">c:geo nie może obliczyć szerokoÅ›ci geograficznej.</string> <string name="err_parse_lon">c:geo nie może obliczyć dÅ‚ugoÅ›ci geograficznej.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Sieć</string> <string name="loc_fused">PoÅ‚Ä…czona</string> <string name="loc_low_power">Niski pobór energii</string> + <string name="loc_home">Koordynaty domowe</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Próba lokalizacji</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Najbliższe</string> <string name="advanced_search_button">Szukaj</string> <string name="stored_caches_button">Zapisane</string> - <string name="any_button">WspółrzÄ™dne</string> + <string name="any_button">Idź do</string> <string name="unknown_scan">c:geo nie znalazÅ‚ żadnego GC-kodu w wynikach skanowania.</string> <string name="caches_no_cache">Brak skrzynek</string> <string name="caches_more_caches">WiÄ™cej skrzynek</string> @@ -264,15 +266,14 @@ <string name="caches_sort_finds">Ile razy znaleziona</string> <string name="caches_sort_state">Stan</string> <string name="caches_sort_storage">Data zapisania w urzÄ…dzeniu</string> + <string name="caches_sort_eventdate">Data wydarzenia</string> <string name="caches_select_mode">Tryb wyboru</string> <string name="caches_select_mode_exit">WyjÅ›cie z trybu wyboru</string> <string name="caches_select_invert">Odwróć zaznaczenie</string> <string name="caches_nearby">Najbliższe</string> <string name="caches_manage">ZarzÄ…dzaj</string> <string name="caches_remove_all">UsuÅ„ wszystkie</string> - <string name="caches_remove_all_confirm">Czy chcesz usunąć wszystkie %s skrzynek z aktualnej listy?</string> <string name="caches_remove_selected">UsuÅ„ wybrane</string> - <string name="caches_remove_selected_confirm">Czy chcesz usunąć wybrane %s skrzynek z urzÄ…dzenia?</string> <string name="caches_remove_progress">Usuwanie skrzynek</string> <string name="caches_delete_events">UsuÅ„ minione wydarzenia</string> <string name="caches_refresh_selected">OdÅ›wież wybrane</string> @@ -292,13 +293,18 @@ <string name="caches_filter_track">Z przedmiotami podróżnymi</string> <string name="caches_filter_clear">UsuÅ„ filtr</string> <string name="caches_filter_modified">Zmiany współrzÄ™dnych</string> + <string name="caches_filter_offline_log">Z wpisami offline</string> <string name="caches_filter_origin">ŹródÅ‚o</string> <string name="caches_filter_distance">OdlegÅ‚ość</string> <string name="caches_filter_personal_note">Zawiera notatkÄ™</string> <string name="caches_filter_popularity">Ulubione</string> <string name="caches_filter_popularity_ratio">Ulubione [%]</string> + <string name="caches_filter_personal_data">Z osobistymi informacjami</string> + <string name="caches_filter_rating">Z ocenÄ…</string> + <string name="caches_filter_own_rating">Z wÅ‚asnÄ… ocenÄ…</string> <string name="caches_removing_from_history">Usuwam z Historii…</string> <string name="caches_clear_offlinelogs">UsuÅ„ wpisy offline</string> + <string name="caches_clear_offlinelogs_message">Czy chcesz wyczyÅ›cić wpisy offline?</string> <string name="caches_clear_offlinelogs_progress">Usuwanie wpisów offline</string> <string name="list_menu_create">Utwórz nowÄ… listÄ™</string> <string name="list_menu_drop">UsuÅ„ aktualnÄ… listÄ™</string> @@ -321,13 +327,17 @@ <string name="list_not_available">Lista nie jest już dostÄ™pna, przechodzÄ™ do standardowej listy</string> <string name="about_version">Wersja</string> <string name="about_changelog">Zmiany</string> + <string name="about_system">System</string> <string name="about_donate">Podaruj</string> <string name="about_donation_more">Darowizna dla\nprogramisty</string> <string name="about_contributors">Współpracownicy</string> <string name="about_license">Licencja</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Pomoc</string> + <string name="about_system_include">ProszÄ™ zaÅ‚Ä…czyć nastÄ™pujÄ…ce informacje o systemie podczas przesyÅ‚ania raportu bÅ‚Ä™du albo podczas proÅ›by o wiÄ™cej informacji odnoÅ›nie c:geo:</string> + <string name="changelog_github">Lista wszystkich zmian</string> <string name="settings_title_services">UsÅ‚ugi</string> + <string name="settings_summary_services">Konfigurowanie informacji o koncie użytkownika i dostÄ™p do usÅ‚ug opcjonalnych.</string> <string name="settings_title_appearance">WyglÄ…d</string> <string name="settings_title_cachedetails">Szczegóły skrzynki</string> <string name="settings_title_offlinedata">Dane offline</string> @@ -371,6 +381,9 @@ <string name="settings_activate_oc_uk">Aktywuj</string> <string name="init_oc_uk_description">Autoryzuj c:geo z opencaching.org.uk aby wyszukiwać skrzynki i mieć dostÄ™p/filtrować znalezione skrzynki.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Aby móc oceniać skrzynki, należy postÄ™pować zgodnie z instrukcjami zawartymi na GCVote.com i podać swoje hasÅ‚o do serwisu tutaj.</string> + <string name="err_gcvote_send_rating">BÅ‚Ä…d podczas wysyÅ‚ania oceny, sprawdź swoje hasÅ‚o do GCVote w ustawieniach albo wyczyść je.</string> + <string name="gcvote_sent">GÅ‚os pomyÅ›lnie oddany</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktywuj</string> <string name="init_username">Nazwa użytkownika</string> @@ -441,6 +454,8 @@ <string name="init_backup_success">Baza danych c:geo zostaÅ‚a pomyÅ›lnie skopiowana do pliku</string> <string name="init_backup_failed">Tworzenie kopii zapasowej bazy danych c:geo nie powiodÅ‚o siÄ™.</string> <string name="init_backup_unnecessary">Baza danych jest pusta, tworzenie kopii zapasowej nie jest potrzebne.</string> + <string name="backup_confirm_overwrite">Czy chcesz nadpisać aktualnÄ… kopiÄ™ zapasowÄ… z %s?</string> + <string name="restore_confirm_overwrite">Czy chcesz nadpisać %s w twoim urzÄ…dzeniu kopiÄ… zapasowÄ…?</string> <string name="init_restore_success">Odzyskiwanie zakoÅ„czone.</string> <string name="init_restore_failed">Odzyskiwanie nie powiodÅ‚o siÄ™.</string> <string name="init_restore_running">Odzyskiwanie bazy skrzynek…</string> @@ -601,6 +616,7 @@ </plurals> <string name="cache_waypoints_add">Dodaj punkt nawigacji</string> <string name="cache_hint">Wskazówka</string> + <string name="cache_hint_not_available">Brak podpowiedzi</string> <string name="cache_logs">Dziennik</string> <string name="cache_logs_friends_and_own">Wpisy przyjaciół/wÅ‚asne</string> <string name="cache_dialog_loading_details">ÅadujÄ™ szczegóły skrzynki…</string> @@ -643,6 +659,7 @@ <string name="cache_menu_visit_offline">Wpisz wizytÄ™ offline</string> <string name="cache_menu_spoilers">ZdjÄ™cia spoiler</string> <string name="cache_menu_around">Skrzynki w pobliżu</string> + <string name="around">W pobliżu %s</string> <string name="cache_menu_event">Dodaj do kalendarza</string> <string name="cache_menu_details">Szczegóły</string> <string name="cache_menu_refresh">OdÅ›wież</string> @@ -652,6 +669,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Zegarek Pebble</string> + <string name="cache_menu_vote">GÅ‚osuj</string> + <string name="cache_menu_checker">Otwórz Geochecker\'a</string> + <string name="cache_menu_ignore">Ignoruj skrzynkÄ™</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">ZapamiÄ™tany wpis</string> <string name="cache_status_found">Znaleziona</string> @@ -737,6 +757,7 @@ <string name="waypoint_note">Notatka</string> <string name="waypoint_visited">Odwiedzony</string> <string name="waypoint_save">Zapisz</string> + <string name="waypoint_cancel_edit">Anuluj</string> <string name="waypoint_loading">ÅadujÄ™ punkt nawigacji…</string> <string name="waypoint_do_not_touch_cache_coordinates">WspółrzÄ™dne skrzynki bez zmian</string> <string name="waypoint_set_as_cache_coords">Ustaw jako współrzÄ™dne skrzynki w c:geo</string> @@ -761,6 +782,8 @@ <string name="search_clear_history">UsuÅ„ historiÄ™</string> <string name="search_history_cleared">Historia usuniÄ™ta</string> <string name="waypoint_coordinate_formats_plain">zwykÅ‚e</string> + <string name="from_clipboard">Ze schowka</string> + <string name="copy_to_clipboard">Kopiuj do schowka</string> <string name="visit_tweet">WyÅ›lij informacjÄ™ do Twitter</string> <string name="map_map">Mapa</string> <string name="map_live">Mapa online</string> @@ -865,7 +888,7 @@ <string name="helper_contacts_description">Umożliwia Tobie otwarcie kontaktu (z Twojej książki adresowej) bezpoÅ›rednio z wpisu do dziennika, wiÄ™c możesz Å‚atwiej poprosić przyjaciół o pomoc.</string> <string name="helper_sendtocgeo_description">WyÅ›lij do c:geo jest rozszerzeniem do przeglÄ…darki <strong>na komputer</strong>. Podczas przeglÄ…dania Geocaching.com pozwala na wysÅ‚anie skrzynek bezpoÅ›rednio do telefonu, za pomocÄ… jednego przycisku w przeglÄ…darce.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Bardzo dobra aplikacja do oglÄ…dania map online, która pozwala na pobieranie ich bezpoÅ›rednio do trybu offline (tylko mapy rastrowe). Pozwala także na zapisywanie Å›cieżek, obsÅ‚ugÄ™ POI oraz ma wiele innych przydatnych funkcji.</string> + <string name="helper_locus_description">Program do nawigacji w terenie dla Twojego telefonu lub tabletu. PrzeglÄ…daj mapy topograficzne offiline, Å›ledź swojÄ… trasÄ™, poluj na skrzynki geocache, używaj nawigacji gÅ‚osowej i wiele wiÄ™cej.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Można wywoÅ‚ać radar bezpoÅ›rednio z aplikacji c:geo. Oferuje on również wiele informacji zwiÄ…zanych z GPS.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1117,13 +1140,15 @@ <string name="attribute_offset_cache_no">Nie jest to skrzynka Offset</string> <string name="quote">Aby uczynić geocaching prostszym, a użytkowników bardziej leniwymi.</string> <string name="powered_by">carnero</string> - <string name="support">Wsparcie: <a href="">support@cgeo.org</a></string> - <string name="website">Website: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo strona</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo w Google Play</a></string> + <string name="support_title">Pomoc</string> + <string name="website_title">Adres strony</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">c:geo na fb</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo w Google Play</a></string> <string name="about_twitter">Czy chczesz aby <b>c:geo</b> publikowaÅ‚ nowy status na Twitter za każdym razem kiedy znajdziesz skrzynkÄ™?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">DostÄ™pna nowa wersja.\nKliknij aby zainstalować.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">DostÄ™pna nowa codzienna wersja.\nKliknij aby zainstalować.</string> <string name="status_new_rc" tools:ignore="UnusedResources">DostÄ™pny nowy kandydat na nowÄ… wersjÄ™.\nKliknij aby zainstalować.</string> @@ -1174,7 +1199,7 @@ <item quantity="few">%s ulubione</item> <item quantity="other">%s ulubionych</item> </plurals> - <string name="percent_favorite_points">%\ ulubionych</string> + <string name="more_than_percent_favorite_points">> %d%% ulubionych</string> <string name="cgeo_shortcut">skrót do c:geo</string> <string name="create_shortcut">Utwórz skrót</string> <string name="send">WyÅ›lij</string> @@ -1184,6 +1209,8 @@ <string name="showcase_main_text">c:geo umieszcza teraz opcje menu w pasku tytuÅ‚owym jak inne współczesne programy. Niektóre opcje sÄ… schowane za kropkowanym symbolem. NaciÅ›nij dÅ‚użej przycisk by zobaczyć opis.</string> <string name="showcase_cachelist_title">PrzeÅ‚Ä…czanie list</string> <string name="showcase_cachelist_text">Możesz przeÅ‚Ä…czać miÄ™dzy listami skrzynek klikajÄ…c tytuÅ‚ listy.</string> + <string name="showcase_compass_hint_title">Podpowiedź</string> + <string name="showcase_compass_hint_text">Ten nowy element menu może Ci pomóc przy szukaniu skrzynki - pokazuje podpowiedź, o ile jest dostÄ™pna.</string> <string name="confirm_log_title">NiezwykÅ‚y typ wpisu</string> <string name="confirm_log_message">Chcesz wpisać \'%s\'. Czy jesteÅ› pewien?</string> </resources> diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml index 6194cce..ea75db1 100644 --- a/main/res/values-pt/strings.xml +++ b/main/res/values-pt/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">Visitei</string> <string name="log_tb_drop">Deixei aqui</string> <string name="log_tb_changeall">Alterar todos</string> - <string name="log_save">Gravar</string> + <string name="log_save">Guardar offline</string> <string name="log_saving">A gravar o registo…</string> <string name="log_saving_and_uploading">A enviar o registo e a imagem…</string> <string name="log_clear">Limpar</string> <string name="log_post_not_possible">A carregar página de registo…</string> + <string name="log_date_future_not_allowed">Registos com datas futuras não são permitidos.</string> <string name="log_add">Adicionar</string> + <string name="log_repeat">Repetir último registo</string> <string name="log_no_rating">Não votar</string> <string name="log_stars_1_description">TerrÃvel</string> <string name="log_stars_15_description">Muito má</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Password do registo:</string> <string name="log_hint_log_password">Inserira a password do registo</string> <string name="log_oc_team_comment">Comentário da OC Team</string> + <string name="log_your_saved_log">O seu registo gravado</string> <string-array name="log_image_scales"> <item>Não dimensionar</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Informação de login não gravada</string> <string name="err_login_failed_toast">O c:geo não consegue fazer login. O c:geo funciona offline com as caches Arquivadas. Verifique as definições de login ou habilite a ligação de dados.</string> <string name="err_unknown">Erro desconhecido</string> + <string name="err_unknown_address">c:geo não conseguiu mapear a morada para uma localização existente</string> <string name="err_comm">Erro de comunicação desconhecido</string> <string name="err_missing_auth">Sem nome de utilizador/password definidos.</string> <string name="err_wrong">Dados de login inválidos</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Aquisição de uma imagem falhou.</string> <string name="err_tb_display">O c:geo não consegue mostrar o trackable pretendido. É mesmo um trackable?</string> <string name="err_tb_details_open">O c:geo não consegue abrir os detalhes do trackable.</string> - <string name="err_tb_forgot_saw">O c:geo esqueceu o trackable que viu.</string> <string name="err_tb_find">O c:geo não encontra o trackable</string> <string name="err_tb_find_that">O c:geo não encontra esse trackable.</string> <string name="err_waypoint_cache_unknown">O c:geo não sabe a que cache quer adicionar o ponto de referência.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">O c:geo não conseguiu reconhecer a sua localização.</string> <string name="err_point_no_position_given_title">Informação requerida</string> <string name="err_point_no_position_given">Preencha pelo menos a latitude, a longitude, a distância ou a direcção. Também pode preencher os quatro campos.</string> - <string name="err_point_curr_position_unavailable">O c:geo ainda não possui as coordenadas actuais. Por favor, aguarde um instante…</string> <string name="err_point_bear_and_dist_title">Precisa de ajuda?</string> <string name="err_point_bear_and_dist">Preencha a direcção e a distância. A direcção é o ângulo de 0 a 360 graus relativo ao norte. A distância pode ser introduzida com ou sem unidades.</string> <string name="err_log_load_data">O c:geo não consegue carregar os dados necessários para registar a sua visita.</string> <string name="err_log_load_data_again">O c:geo não consegue carregar os dados necessários para registar a sua visita. A tentar de novo.</string> <string name="err_log_load_data_still">O c:geo ainda está a carregar dados necessários para publicar o registo. Por favor espere mais um pouco.</string> - <string name="err_log_post_failed">O c:geo falhou a publicação do registo.</string> - <string name="err_log_post_failed_ec">Parece que o seu log não foi publicado. Por favor verifique-o em Extremcaching.com.</string> - <string name="err_logimage_post_failed">Parece que a sua imagem de registo não foi enviada. Por favor verifique em Geocaching.com.</string> + <string name="err_log_post_failed">Parece que o seu registo não foi publicado. Por favor, verifique a página Web original da cache.</string> + <string name="err_logimage_post_failed">Parece que a imagem do seu registo não foi enviada. Por favor, verifique a página Web original da cache.</string> <string name="err_search_address_forgot">O c:geo esqueceu o endereço que procura.</string> <string name="err_parse_lat">O c:geo não consegue analisar a latitue.</string> <string name="err_parse_lon">O c:geo não consegue analisar a logitude.</string> @@ -209,6 +210,9 @@ <string name="info_cache_saved">A cache foi armazenada localmente</string> <string name="loc_last">Último conhecido</string> <string name="loc_net">Rede</string> + <string name="loc_fused">Combinados</string> + <string name="loc_low_power">Bateria fraca</string> + <string name="loc_home">Coordenadas de casa</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">A tentar localizar</string> @@ -227,7 +231,7 @@ <string name="caches_nearby_button">Por perto</string> <string name="advanced_search_button">Pesquisar</string> <string name="stored_caches_button">Arquivo</string> - <string name="any_button">Destino</string> + <string name="any_button">Ir para</string> <string name="unknown_scan">Sem resultados do scan.</string> <string name="caches_no_cache">Nenhuma cache</string> <string name="caches_more_caches">Mais caches</string> @@ -261,15 +265,18 @@ <string name="caches_sort_finds">Encontradas</string> <string name="caches_sort_state">Estado</string> <string name="caches_sort_storage">Data gravada no dispositivo</string> + <string name="caches_sort_eventdate">Data do evento</string> <string name="caches_select_mode">Modo de selecção</string> <string name="caches_select_mode_exit">Sair do modo de selecção</string> <string name="caches_select_invert">Inverter selecção</string> <string name="caches_nearby">Por perto</string> <string name="caches_manage">Gerir</string> <string name="caches_remove_all">Remover todas</string> - <string name="caches_remove_all_confirm">Quer remover todas as %s caches da lista atual?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Quer remover esta cache da lista actual?</item> + <item quantity="other">Quer remover todas as %d caches da lista actual?</item> + </plurals> <string name="caches_remove_selected">Remover selecionadas</string> - <string name="caches_remove_selected_confirm">Quer remover as %s caches selecionadas do seu dispositivo?</string> <string name="caches_remove_progress">A remover caches</string> <string name="caches_delete_events">Eliminar eventos passados</string> <string name="caches_refresh_selected">Actualizar seleccionada</string> @@ -289,13 +296,18 @@ <string name="caches_filter_track">Com trackables</string> <string name="caches_filter_clear">Limpar filtros</string> <string name="caches_filter_modified">Com as coordenadas modificadas</string> + <string name="caches_filter_offline_log">Com registo offline</string> <string name="caches_filter_origin">Origem</string> <string name="caches_filter_distance">Distância</string> <string name="caches_filter_personal_note">Com nota pessoal</string> <string name="caches_filter_popularity">Favoritos</string> <string name="caches_filter_popularity_ratio">Favoritos [%]</string> + <string name="caches_filter_personal_data">Com notas pessoais</string> + <string name="caches_filter_rating">Com classificação</string> + <string name="caches_filter_own_rating">Com própria classificação</string> <string name="caches_removing_from_history">A remover do histórico…</string> <string name="caches_clear_offlinelogs">Limpar registos offline</string> + <string name="caches_clear_offlinelogs_message">Quer apagar os registos offline?</string> <string name="caches_clear_offlinelogs_progress">A limpar registos offline</string> <string name="list_menu_create">Criar nova lista</string> <string name="list_menu_drop">Apagar lista actual</string> @@ -318,13 +330,17 @@ <string name="list_not_available">A lista já não se encontra disponÃvel, alterando para lista padrão</string> <string name="about_version">Versão</string> <string name="about_changelog">Changelog</string> + <string name="about_system">Sistema</string> <string name="about_donate">Doar</string> <string name="about_donation_more">Doar\ndesenvolvimento</string> <string name="about_contributors">Contribuidores</string> <string name="about_license">Licença</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Ajuda</string> + <string name="about_system_include">Por favor inclua as seguintes informações de sistema ao enviar um relatório de bug ou ao pedir mais informações sobre c:geo:</string> + <string name="changelog_github">Lista de todas as alterações</string> <string name="settings_title_services">Serviços</string> + <string name="settings_summary_services">Configure a informação da conta de utilizador e o acesso a serviços opcionais.</string> <string name="settings_title_appearance">Aparência</string> <string name="settings_title_cachedetails">Detalhos da Cache</string> <string name="settings_title_offlinedata">Dados Offline</string> @@ -371,6 +387,9 @@ <string name="settings_activate_oc_uk">Ativar</string> <string name="init_oc_uk_description">Autorizar o c:geo em opencaching.org.uk para que pesquise por caches e aceder/filtrar as suas caches encontradas.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Para poder classificar uma cache, tem que seguir as instruções em GCVote.com e digitar a sua senha GCVote aqui.</string> + <string name="err_gcvote_send_rating">Erro ao enviar a classificação, verifique a senha do GCVote nas configurações ou limpe a mesma.</string> + <string name="gcvote_sent">Votação enviada com sucesso</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activar</string> <string name="init_username">Nome de utilizador</string> @@ -441,6 +460,8 @@ <string name="init_backup_success">A base de dados do c:geo foi copiada com sucesso</string> <string name="init_backup_failed">O backup da base de dados do c:geo falhou.</string> <string name="init_backup_unnecessary">Base de dados vazia, não é necessário um backup.</string> + <string name="backup_confirm_overwrite">Quer substituir o backup existente de %s?</string> + <string name="restore_confirm_overwrite">Quer substituir %s no seu dispositivo com o backup?</string> <string name="init_restore_success">Restauro concluÃdo.</string> <string name="init_restore_failed">O restauro falhou.</string> <string name="init_restore_running">A restaurar a base de dados de caches…</string> @@ -489,9 +510,18 @@ <string name="init_maintenance">Manutenção</string> <string name="init_maintenance_directories_note">c:geo armazena imagens, registo de imagens e outros ficheiros relacionados com uma cache numa pasta separada. Nalguns casos (como ao importar/exportar a base de dados) esta pasta pode conter ficheiros desatualizados, que podem ser apagados aqui.</string> <string name="init_maintenance_directories">Apagar ficheiros orfãos</string> + <string name="init_location">Geolocalização</string> + <string name="init_location_note">Em dispositivos equipados com serviços Google Play, o c:geo pode automaticamente usar um melhor fornecedor de geolocalização. No entanto, isso impede o uso de um receptor GPS BlueTooth externo.</string> + <string name="init_location_googleplayservices">Utilizar serviços Google Play</string> + <string name="init_low_power">Modo de baixo consumo de energia</string> + <string name="init_low_power_note">O modo de baixo consumo de energia evita usar o GPS e o giroscópio quando não é necessária uma localização muito precisa, à custa de tempos de fixação mais longos.</string> + <string name="init_low_power_mode">Ativar modo de baixo consumo de energia</string> <string name="init_create_memory_dump">criar dump de memória</string> <string name="init_memory_dump">dump de memória</string> <string name="init_memory_dumped">dump de memória em %s</string> + <string name="init_hardware_acceleration_title">Renderização acelerada por hardware</string> + <string name="init_hardware_acceleration_note">Aceleração por hardware processa elementos gráficos mais rapidamente no ecrã. No entanto, em alguns dispositivos o sistema operativo Android contém erros e algum texto pode aparecer desfocado (nomeadamente caracteres em negrito). Desactive a aceleração por hardware se isso lhe acontecer.</string> + <string name="init_hardware_acceleration">Activar renderização acelerada por hardware</string> <string name="settings_open_website">Abrir o website</string> <string name="settings_settings">Definições</string> <string name="settings_information">Informações</string> @@ -590,6 +620,7 @@ </plurals> <string name="cache_waypoints_add">Adicionar ponto de referência</string> <string name="cache_hint">Pista</string> + <string name="cache_hint_not_available">Nenhuma pista disponÃvel</string> <string name="cache_logs">Logbook</string> <string name="cache_logs_friends_and_own">Registos de amigos/próprios</string> <string name="cache_dialog_loading_details">A carregar os detalhes da cache…</string> @@ -629,9 +660,10 @@ <string name="cache_menu_streetview">Vista de rua</string> <string name="cache_menu_browser">Abrir no browser</string> <string name="cache_menu_visit">Registar visita</string> - <string name="cache_menu_visit_offline">Registar visita offline</string> + <string name="cache_menu_visit_offline">Registo offline rápido</string> <string name="cache_menu_spoilers">Imagens spoiler</string> <string name="cache_menu_around">Caches próximas</string> + <string name="around">Perto de %s</string> <string name="cache_menu_event">Adicionar ao calendário</string> <string name="cache_menu_details">Detalhes</string> <string name="cache_menu_refresh">Actualizar</string> @@ -641,6 +673,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Seixo</string> + <string name="cache_menu_vote">Voto</string> + <string name="cache_menu_checker">Abrir Geochecker</string> + <string name="cache_menu_ignore">Ignorar a cache</string> <string name="cache_status">Estado</string> <string name="cache_status_offline_log">Registo gravado</string> <string name="cache_status_found">Encontrada</string> @@ -726,6 +761,7 @@ <string name="waypoint_note">Nota</string> <string name="waypoint_visited">Visitado</string> <string name="waypoint_save">Gravar</string> + <string name="waypoint_cancel_edit">Cancelar</string> <string name="waypoint_loading">A carregar ponto de referência…</string> <string name="waypoint_do_not_touch_cache_coordinates">Nenhuma mudança à s coordenadas da cache</string> <string name="waypoint_set_as_cache_coords">Definir como coordenadas da cache no c:geo</string> @@ -750,6 +786,8 @@ <string name="search_clear_history">Limpar histórico</string> <string name="search_history_cleared">Histórico limpo</string> <string name="waypoint_coordinate_formats_plain">Plano</string> + <string name="from_clipboard">Da área de transferência</string> + <string name="copy_to_clipboard">Copiar para área de transferência</string> <string name="visit_tweet">Publicar esta descoberta no Twitter</string> <string name="map_map">Mapa</string> <string name="map_live">Mapa ao vivo</string> @@ -854,7 +892,7 @@ <string name="helper_contacts_description">Permite abrir um contacto (da sua agenda telefónica) directamente a partir de um log. Assim será mais fácil de pedir ajuda aos seus amigos.</string> <string name="helper_sendtocgeo_description">Send to c:geo é uma extensão do navegador <strong>para o seu PC</strong>. Ao navegar geocaching.com, você pode enviar as caches directamente para seu smartphone com o clique de um botão no navegador.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Aplicação simples e útil, que mostra mapas online e permite transferi-los directamente para o modo offline (apenas mapas raster). Também suporta a gravação de caminhos, gestão de PDI e muitas outras funções úteis.</string> + <string name="helper_locus_description">Aplicação de navegação ao ar livre para o seu telefone ou tablet. Veja mapas topográficos offline, registe a sua rota, procure geocaches, use um guia de voz e muito mais.</string> <string name="helper_gpsstatus_title">Estado do GPS</string> <string name="helper_gpsstatus_description">Pode usar o radar a partir desta aplicação. Também fornece muitas outras informações relacionadas com o GPS.</string> <string name="helper_bluetoothgps_title">GPS por bluetooth</string> @@ -1106,13 +1144,15 @@ <string name="attribute_offset_cache_no">Cache sem offset de translação</string> <string name="quote">Para tornar o geocaching mais fácil, para tornar os utilizadores mais preguiçosos.</string> <string name="powered_by">carnero</string> - <string name="support">Suporte: <a href="">support@cgeo.org</a></string> - <string name="website">Site na internet: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">página do c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo no Google Play</a></string> + <string name="support_title">Suporte</string> + <string name="website_title">Página Web</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">Página do c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo no Google Play</a></string> <string name="about_twitter">O <b>c:geo</b> deve publicar no Twitter de cada vez que uma cache foi registrada?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">Perguntas Frequentes</string> <string name="status_new_release" tools:ignore="UnusedResources">Nova versão disponÃvel.\nClique para instalar.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nova \'nightly build\' disponÃvel.\nClique para instalar.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Nova \'release candidate\' disponÃvel .\nClique para instalar.</string> @@ -1123,6 +1163,8 @@ <string name="tts_service">Bússola que fala</string> <string name="tts_start">Comece a falar</string> <string name="tts_stop">Páre de falar</string> + <string name="tts_started">Iniciou fala</string> + <string name="tts_stopped">Parou fala</string> <string name="err_tts_lang_not_supported">A linguagem corrente não é suportada pelo texto em fala.</string> <string name="tts_one_kilometer">um quilômetro</string> <plurals name="tts_kilometers"> @@ -1155,8 +1197,17 @@ <item quantity="one">%s favorito</item> <item quantity="other">%s favoritos</item> </plurals> - <string name="percent_favorite_points">%\ favoritos</string> + <string name="more_than_percent_favorite_points">> %d%% favoritos</string> <string name="cgeo_shortcut">Atalho c:geo</string> <string name="create_shortcut">Criar atalho</string> <string name="send">Enviar</string> + <string name="showcase_logcache_title">Enviando o registo</string> + <string name="showcase_logcache_text">Lembre-se, muitos comandos estão agora na barra de tÃtulo. Lá encontra o botão para enviar o registo terminado.</string> + <string name="showcase_main_title">Novos menus</string> + <string name="showcase_main_text">c:Geo coloca agora itens de menu na barra de tÃtulo como outras aplicações modernas. Alguns itens estão escondidos atrás do sÃmbolo dos pontos. Prima longamente um botão para ver sua descrição.</string> + <string name="showcase_cachelist_title">A trocar de listas</string> + <string name="showcase_cachelist_text">Pode alternar entre listas de caches clicando no tÃtulo da lista.</string> + <string name="showcase_compass_hint_title">Mostrar a dica</string> + <string name="confirm_log_title">Tipo de registo invulgar</string> + <string name="confirm_log_message">Quer fazer o registo \'%s\'. Tem a certeza?</string> </resources> diff --git a/main/res/values-ro/strings.xml b/main/res/values-ro/strings.xml index 857598f..6385c7a 100644 --- a/main/res/values-ro/strings.xml +++ b/main/res/values-ro/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">Vizitat</string> <string name="log_tb_drop">Lăsat</string> <string name="log_tb_changeall">Schimbă toate</string> - <string name="log_save">Salvează</string> + <string name="log_save">Salvează local</string> <string name="log_saving">Trimitere jurnal…</string> <string name="log_saving_and_uploading">Trimitre jurnal ÅŸi încarcare poze…</string> <string name="log_clear">Åžterge</string> <string name="log_post_not_possible">ÃŽncărcare pagină însemnări…</string> + <string name="log_date_future_not_allowed">Nu sunt permise însemnări datate în viitor.</string> <string name="log_add">Adaugă</string> + <string name="log_repeat">Repetă ultima însemnare</string> <string name="log_no_rating">Fără voturi</string> <string name="log_stars_1_description">Foarte slabă</string> <string name="log_stars_15_description">Slabă</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Parolă:</string> <string name="log_hint_log_password">Introdu parola pentru jurnal</string> <string name="log_oc_team_comment">Comentariu din partea echipei OC</string> + <string name="log_your_saved_log">ÃŽnsemnare salvată</string> <string-array name="log_image_scales"> <item>Fără redimensionare</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Nu există informaÅ£ii de autorizare</string> <string name="err_login_failed_toast">c:geo nu se poate conecta. c:geo va funcÅ£iona deconectat cu cutiile salvate local. Verifică informaÅ£iile de autentificare sau activează conexiunea la internet.</string> <string name="err_unknown">Eroare necunoscută</string> + <string name="err_unknown_address">c:geo nu a putut găsi coordonate pentru această adresă</string> <string name="err_comm">Eroare necunoscută de comunicaÅ£ie</string> <string name="err_missing_auth">Nu a fost dat numele de utilizator sau parola.</string> <string name="err_wrong">InformaÅ£ii de autentificare incorecte</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Imaginea nu a putut fi obÅ£inută.</string> <string name="err_tb_display">c:geo nu poate afiÅŸa obiectul călător solicitat. Chiar este un obiect călător?</string> <string name="err_tb_details_open">c:geo nu poate accesa detaliile obiectului călător.</string> - <string name="err_tb_forgot_saw">c:geo a uitat obiectul călător pe care l-ai văzut.</string> <string name="err_tb_find">c:geo nu poate găsi obiectul călător</string> <string name="err_tb_find_that">c:geo nu poate găsi acest obiect călător.</string> <string name="err_waypoint_cache_unknown">c:geo nu ÅŸtie pentru ce cutie vrei sa adaugi un punct.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo nu poate determina unde te afli.</string> <string name="err_point_no_position_given_title">InformaÅ£ii necesare</string> <string name="err_point_no_position_given">Introdu cel puÅ£in latitudine ÅŸi longitudine sau distanţă ÅŸi azimut. Se pot completa ÅŸi toate cele patru câmpuri.</string> - <string name="err_point_curr_position_unavailable">c:geo incă tot nu a obÅ£inut coordonatele poziÅ£iei curente. Te rog, mai aÅŸteaptă puÅ£in…</string> <string name="err_point_bear_and_dist_title">Ai nevoie de ajutor?</string> <string name="err_point_bear_and_dist">Completează ÅŸi azimutul ÅŸi distanÅ£a. Azimutul este unghiul de la 0 la 360 faţă de nord. DistanÅ£a nu necesită unităţi.</string> <string name="err_log_load_data">c:geo nu poate încărca informaÅ£iile necesare pentru a posta o însemnare.</string> <string name="err_log_load_data_again">c:geo nu poate încărca informaÅ£iile necesare pentru a posta o însemnare. Te rog încearcă din nou.</string> <string name="err_log_load_data_still">c:geo încă încarcă informaÅ£iale necesare pentru a posta o însemnare. Te rog mai aÅŸteaptă.</string> - <string name="err_log_post_failed">Se pare că însemnarea nu a fost postată. Verifică pe Geocaching.com.</string> - <string name="err_log_post_failed_ec">Se pare că însemnarea nu a fost postată. Verifică pe Extremcaching.com.</string> - <string name="err_logimage_post_failed">Se pare că imaginea ataÅŸată însemnării nu a fost postată. Verifică pe Geocaching.com.</string> + <string name="err_log_post_failed">Se pare că însemnarea ta nu a fost postată. Te rog verifică pe site-ul pe care se află publicată această geocutie.</string> + <string name="err_logimage_post_failed">Se pare că imaginea pe care încercai să o trimiÅ£i odată cu însemnarea nu a putut fi încărcată. Te rog verifică însemnarea în jurnalul geocutiei pe site-ul unde este publicată.</string> <string name="err_search_address_forgot">c:geo a uitat adresa pe care o căutai.</string> <string name="err_parse_lat">c:geo nu înÅ£elege latitudinea.</string> <string name="err_parse_lon">c:geo nu înÅ£elege longitudinea.</string> @@ -211,6 +212,7 @@ <string name="loc_net">ReÅ£ea</string> <string name="loc_fused">Combinat</string> <string name="loc_low_power">Mod economic</string> + <string name="loc_home">Coordonatele de acasă</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">ÃŽncerc să determin poziÅ£ia</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">ÃŽn apropiere</string> <string name="advanced_search_button">Caută</string> <string name="stored_caches_button">Stocate</string> - <string name="any_button">Orice destinaÅ£ie</string> + <string name="any_button">Coordonate</string> <string name="unknown_scan">Nu a fost găsit nici un geocod în rezultatul scanării.</string> <string name="caches_no_cache">Nici o cutie</string> <string name="caches_more_caches">ÃŽncarcă mai multe cutii</string> @@ -256,7 +258,7 @@ <string name="caches_sort_favorites_ratio">Favorite [%]</string> <string name="caches_sort_name">Nume</string> <string name="caches_sort_geocode">Geo Cod</string> - <string name="caches_sort_rating">Rating</string> + <string name="caches_sort_rating">Voturi</string> <string name="caches_sort_vote">Vot (propriul vot)</string> <string name="caches_sort_inventory">Total inventar</string> <string name="caches_sort_date_hidden">Data ascunderii</string> @@ -264,15 +266,24 @@ <string name="caches_sort_finds">Găsite</string> <string name="caches_sort_state">Stare</string> <string name="caches_sort_storage">Data salvării pe acest dispozitiv</string> + <string name="caches_sort_eventdate">Data evenimentului</string> <string name="caches_select_mode">Mod selecÅ£ie</string> <string name="caches_select_mode_exit">Renunţă la modul selecÅ£ie</string> <string name="caches_select_invert">Inversează selecÅ£ia</string> <string name="caches_nearby">ÃŽn apropiere</string> <string name="caches_manage">Gestionează</string> <string name="caches_remove_all">Șterge toate</string> - <string name="caches_remove_all_confirm">Vrei să ÅŸtergi toate cele %s cutii din lista curenă?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Vrei să ÅŸtergi această geocutie din lista curentă?</item> + <item quantity="few">Vrei să ÅŸtergi toate cele %d geocutii din lista curentă?</item> + <item quantity="other">Vrei să ÅŸtergi toate cele %d geocutii din lista curentă?</item> + </plurals> <string name="caches_remove_selected">Åžterge geocutiile selectate</string> - <string name="caches_remove_selected_confirm">Vrei să ÅŸtergi cele %s cutii selectate din dispozitiv?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Vrei să ÅŸtergi această geocutie din dispozitivul tău?</item> + <item quantity="few">Vrei să ÅŸtergi cele %d geocutii selectate din dispozitivul tău?</item> + <item quantity="other">Vrei să ÅŸtergi cele %d geocutii selectate din dispozitivul tău?</item> + </plurals> <string name="caches_remove_progress">Åžtergere geocutii</string> <string name="caches_delete_events">Åžterge evenimentele trecute</string> <string name="caches_refresh_selected">Reîncarcă cutiile selectate</string> @@ -292,13 +303,18 @@ <string name="caches_filter_track">ConÅ£ine obiecte călătoare</string> <string name="caches_filter_clear">Anulează filtrele</string> <string name="caches_filter_modified">Cu coordonate modificate</string> + <string name="caches_filter_offline_log">Cu însemnări salvate</string> <string name="caches_filter_origin">Origine</string> <string name="caches_filter_distance">Distanţă</string> <string name="caches_filter_personal_note">Scrie notă personală</string> <string name="caches_filter_popularity">Favorite</string> <string name="caches_filter_popularity_ratio">Favorite [%]</string> + <string name="caches_filter_personal_data">Cu date personalizate</string> + <string name="caches_filter_rating">Cu voturi</string> + <string name="caches_filter_own_rating">Cu votul tău</string> <string name="caches_removing_from_history">Åžterge din istoric…</string> <string name="caches_clear_offlinelogs">Åžterge însemnări stocate local</string> + <string name="caches_clear_offlinelogs_message">Vrei să ÅŸtergi însemnările stocate local?</string> <string name="caches_clear_offlinelogs_progress">Åžtergere însemnări stocate local</string> <string name="list_menu_create">Crează listă nouă</string> <string name="list_menu_drop">Åžterge lista curentă</string> @@ -321,13 +337,17 @@ <string name="list_not_available">Lista nu mai există, revenire la lista standard</string> <string name="about_version">Versiune</string> <string name="about_changelog">Istoric modificări</string> + <string name="about_system">Sistem</string> <string name="about_donate">Donează</string> <string name="about_donation_more">Donează pentru\ndezvoltare</string> <string name="about_contributors">Contribuitori</string> <string name="about_license">Licenţă</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Ajutor</string> + <string name="about_system_include">Te rog include urmatoarele informaÅ£ii despre sistem atunci când trimiÅ£i o sesizare sau întrebi despre c:geo:</string> + <string name="changelog_github">AfiÅŸează toate modificările</string> <string name="settings_title_services">Servicii internet</string> + <string name="settings_summary_services">Configurează-Å£i contul ÅŸi accesul la servicii opÅ£ionale.</string> <string name="settings_title_appearance">Aspect vizual</string> <string name="settings_title_cachedetails">Detalii cutie</string> <string name="settings_title_offlinedata">InformaÅ£ii păstrate locale</string> @@ -374,6 +394,9 @@ <string name="settings_activate_oc_uk">Activează</string> <string name="init_oc_uk_description">Autorizează c:geo cu opencaching.org.uk pentru a putea căuta geocutii ÅŸi a putea accesa/filtra pe cele găsite de tine.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Pentru a putea evalua o geocutie, trebuie să urmezi instrucÅ£iunile de la GCVote.com ÅŸi să introduci aici parola GCVote.</string> + <string name="err_gcvote_send_rating">Eroare la trimiterea evaluării, verifică-Å£i parola GCVote din configuraÅ£ie sau ÅŸterge această parolă.</string> + <string name="gcvote_sent">Votul a fost trimis</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activează</string> <string name="init_username">Utilizator</string> @@ -444,6 +467,8 @@ <string name="init_backup_success">Baza de date a c:geo a fost copiată aici:</string> <string name="init_backup_failed">Salvarea bazei de date a eÅŸuat.</string> <string name="init_backup_unnecessary">Baza de date este goală. Nu este necesară o salvare de siguranţă.</string> + <string name="backup_confirm_overwrite">Vrei să scrii peste salvarea de siguranţă din %s?</string> + <string name="restore_confirm_overwrite">Vrei să înlocuieÅŸti %s din dispozitivul tău cu cele din salvarea de siguranţă?</string> <string name="init_restore_success">Restaurare finalizată.</string> <string name="init_restore_failed">Restaurarea nu a reuÈ™it.</string> <string name="init_restore_running">Restaurare bază de date cutii…</string> @@ -596,6 +621,7 @@ <string name="cache_waypoints">Puncte</string> <string name="cache_waypoints_add">Adaugă punct</string> <string name="cache_hint">Indiciu</string> + <string name="cache_hint_not_available">Fără indiciu</string> <string name="cache_logs">Jurnal</string> <string name="cache_logs_friends_and_own">ÃŽnsemnări proprii/de la prieteni</string> <string name="cache_dialog_loading_details">ÃŽncărcare detaliile cutiei…</string> @@ -635,9 +661,10 @@ <string name="cache_menu_streetview">Vedere stradală</string> <string name="cache_menu_browser">AfiÅŸează în browser</string> <string name="cache_menu_visit">Jurnal</string> - <string name="cache_menu_visit_offline">Jurnal salvat</string> + <string name="cache_menu_visit_offline">ÃŽnsemnare locală cu un singur clic</string> <string name="cache_menu_spoilers">Imagini (indicii?)</string> <string name="cache_menu_around">Cutii din împrejurimi</string> + <string name="around">Aproximativ %s</string> <string name="cache_menu_event">Adaugă la calendar</string> <string name="cache_menu_details">Detalii</string> <string name="cache_menu_refresh">ÃŽmprospătează</string> @@ -647,6 +674,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Ceas \"Pebble\"</string> + <string name="cache_menu_vote">Votează</string> + <string name="cache_menu_checker">Accesează Geochecker</string> + <string name="cache_menu_ignore">Ignoră geocutia</string> <string name="cache_status">Stare</string> <string name="cache_status_offline_log">Jurnal salvat</string> <string name="cache_status_found">Găsit</string> @@ -732,6 +762,7 @@ <string name="waypoint_note">Notă</string> <string name="waypoint_visited">Vizitat</string> <string name="waypoint_save">Salvează</string> + <string name="waypoint_cancel_edit">Anulează</string> <string name="waypoint_loading">ÃŽncărcare punct…</string> <string name="waypoint_do_not_touch_cache_coordinates">Nu se modifică coordonatele cutiei</string> <string name="waypoint_set_as_cache_coords">Salvează ca coordonatele geocutiei în c:geo</string> @@ -756,6 +787,8 @@ <string name="search_clear_history">Åžterge istoric</string> <string name="search_history_cleared">Istoric ÅŸters</string> <string name="waypoint_coordinate_formats_plain">Simplu</string> + <string name="from_clipboard">Din memoria temporară</string> + <string name="copy_to_clipboard">Copiază în memoria temporară</string> <string name="visit_tweet">Publică pe Twitter</string> <string name="map_map">Hartă</string> <string name="map_live">Hartă</string> @@ -860,7 +893,7 @@ <string name="helper_contacts_description">Permite să afiÅŸezi contacte (din agenda de contacte) direct din formularul pentru însemnări, astfel încÅ£t să ăti poÅ£i întreba mai uÅŸor prietenii.</string> <string name="helper_sendtocgeo_description">Send to c:geo este o extensie pentru browser-ul <strong>de pe PC</strong>. Când vizitezi geocaching.com, poÅ£i trimite geocutii direct către dispozitivul tău apăsând un simplu buton.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">AplicaÅ£ie simplă care afiÅŸează hărÅ£i de pe internet ÅŸi îţi permite să le salvezi local (doar caimagini cu hărÅ£i). Mai ÅŸtie să înregistreze trasee, gestiune de puncte de interes ÅŸi alte funcÅ£ii utile.</string> + <string name="helper_locus_description">AplicaÅ£ie de navigare pentru telefon sau tabletă. Vezi hărÅ£i salvate, urmăreÅŸte-Å£i traseul, caută geocutii, foloseÅŸte ghidare vocală ÅŸi multe altele.</string> <string name="helper_gpsstatus_title">Stare GPS</string> <string name="helper_gpsstatus_description">PoÅ£i folosi ecranul Radar din această aplicaÅ£ie împreună cu c:geo. Oferă ÅŸi multe alte informaÅ£ii legate de GPS.</string> <string name="helper_bluetoothgps_title">GPS prin Bluetooth</string> @@ -1112,13 +1145,15 @@ <string name="attribute_offset_cache_no">Nu este geocutie decalată</string> <string name="quote">Pentru geocaching mai uÅŸor, pentru căutători mai leneÅŸi.</string> <string name="powered_by">carnero</string> - <string name="support">Suport: <a href="">support@cgeo.org</a></string> - <string name="website">Site: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">pagina c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo pe Google Play</a></string> + <string name="support_title">Suport</string> + <string name="website_title">Pagină Web</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">pagina c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo pe Google Play</a></string> <string name="about_twitter">Ar trebui ca <b>c:geo</b> să publice un statut nou pe Twitter de fiecare dată când scrii o însemnare pentru o geocutie?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">ÃŽntrebari frecvente</string> <string name="status_new_release" tools:ignore="UnusedResources">A apărut o versiune nouă.\nApasă aici pentru a instala.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">A apărut o nouă versiune zilnică.\nApasă aici pentru a instala.</string> <string name="status_new_rc" tools:ignore="UnusedResources">A apărut o un candidat pentru o versiune nouă.\nApasă aici pentru a instala.</string> @@ -1138,8 +1173,8 @@ <string name="tts_one_foot">un picior</string> <string name="tts_one_oclock">ora unu</string> <string name="tts_oclock">ora %s</string> - <string name="clipboard_copy_ok">Copiat</string> - <string name="percent_favorite_points">%\ favorite</string> + <string name="clipboard_copy_ok">Copiat în memoria temporară</string> + <string name="more_than_percent_favorite_points">> %d%% favorite</string> <string name="cgeo_shortcut">legătură la c:geo</string> <string name="create_shortcut">Crează scurtătură</string> <string name="send">Trimite</string> @@ -1149,6 +1184,8 @@ <string name="showcase_main_text">c:geo foloseÅŸte meniu în bara de titlu precum alte aplicaÅ£ii moderne. Unele elemente sunt ascunse în spatele simbolului punctat. O apăsare prelungită pe un buton afiÅŸează descrierea acestuia.</string> <string name="showcase_cachelist_title">Comutare între liste</string> <string name="showcase_cachelist_text">PoÅ£i să schimbi lista afiÅŸată apăsând pe titlul listei.</string> + <string name="showcase_compass_hint_title">Arată indiciu</string> + <string name="showcase_compass_hint_text">Această opÅ£iune îţi poate da informaÅ£ii suplimentare despre unde ar putea fi ascunsă geocutia - afiÅŸează indiciul, dacă există.</string> <string name="confirm_log_title">Tip neobiÅŸnuit de însemnare</string> <string name="confirm_log_message">Vrei să scrii o însemnare pentru \'%s\'. EÅŸti sigur?</string> </resources> diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index 57706e4..b796eeb 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -74,12 +74,14 @@ <string name="log_tb_visit">NavÅ¡tÃvené</string> <string name="log_tb_drop">NechaÅ¥ tu</string> <string name="log_tb_changeall">ZmeniÅ¥ vÅ¡etko</string> - <string name="log_save">UložiÅ¥</string> + <string name="log_save">UložiÅ¥ offline</string> <string name="log_saving">Ukladanie logu…</string> <string name="log_saving_and_uploading">Odosielanie logu a nahrávanie obrázku…</string> <string name="log_clear">VyÄistiÅ¥</string> <string name="log_post_not_possible">NaÄÃtanie stránky s logmi…</string> + <string name="log_date_future_not_allowed">Log s budúcim dátumom nie je povolený.</string> <string name="log_add">PridaÅ¥</string> + <string name="log_repeat">ZopakovaÅ¥ posledný log</string> <string name="log_no_rating">NehlasovaÅ¥</string> <string name="log_stars_1_description">slabé</string> <string name="log_stars_15_description">dosÅ¥ slabé</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Logovacie heslo:</string> <string name="log_hint_log_password">Zadajte svoje logovacie heslo</string> <string name="log_oc_team_comment">Komentár tÃmu OC</string> + <string name="log_your_saved_log">Tvoj uložený log</string> <string-array name="log_image_scales"> <item>Bez zmeny mierky</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Nie sú uložené žiadne prihlasovacie údaje.</string> <string name="err_login_failed_toast">PrepáÄte, c:geo sa nepodarilo prihlásiÅ¥. c:geo funguje v offline režime. Skontrolujte vaÅ¡e prihlasovacie údaje v nastaveniach alebo povoľte pripojenie k Internetu.</string> <string name="err_unknown">Neznáma chyba</string> + <string name="err_unknown_address">c:geo nedokázal nájsÅ¥ miesto k daným súradniciam</string> <string name="err_comm">Neznáma chyba pri komunikácii</string> <string name="err_missing_auth">Nevyplnené použÃvateľské meno a/alebo heslo.</string> <string name="err_wrong">Prihlasovacie údaje sú nesprávne</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">ZÃskavanie obrázku zlyhalo.</string> <string name="err_tb_display">PrepáÄte, c:geo nemôže zobraziÅ¥ trasovateľný predmet. Je to naozaj trasovateľný predmet?</string> <string name="err_tb_details_open">PrepáÄte, c:geo nemôže otvoriÅ¥ podrobnosti k trasovateľnému predmetu.</string> - <string name="err_tb_forgot_saw">c:geo zabudlo, ktorý trasovateľný predmet ste videli.</string> <string name="err_tb_find">c:geo nemôže nájsÅ¥ trasovateľný predmet.</string> <string name="err_tb_find_that">c:geo nemôže nájsÅ¥ tento trasovateľný predmet.</string> <string name="err_waypoint_cache_unknown">c:geo nevie, ku ktorej skrýši chcete pridaÅ¥ bod trasy.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">c:geo nevie, kde ste.</string> <string name="err_point_no_position_given_title">Popis je požadovaný</string> <string name="err_point_no_position_given">Vyplňte aspoň zemepisnú Å¡Ãrku a dĺžku alebo vzdialenosÅ¥ a azimut. Môžete tiež vyplniÅ¥ vÅ¡etky Å¡tyri polia.</string> - <string name="err_point_curr_position_unavailable">c:geo stále nepozná aktuálnu polohu. ProsÃm, Äakajte…</string> <string name="err_point_bear_and_dist_title">Potrebujete poradiÅ¥?</string> <string name="err_point_bear_and_dist">Vyplňte azimut aj vzdialenosÅ¥. Azimut je uhol 0 až 360 stupňov vzhľadom k severu. VzdialenosÅ¥ môžete zadaÅ¥ bez jednotiek.</string> <string name="err_log_load_data">c:geo nemôže naÄÃtaÅ¥ dáta potrebné pre zalogovanie návÅ¡tevy.</string> <string name="err_log_load_data_again">c:geo nemôže naÄÃtaÅ¥ dáta potrebné pre zalogovanie návÅ¡tevy. Skúša to znovu.</string> <string name="err_log_load_data_still">c:geo stále naÄÃtava dáta potrebné pre zalogovanie návÅ¡tevy. ProsÃm, poÄkajte chvÃľu.</string> - <string name="err_log_post_failed">c:geo pravdepodobne nemohlo odoslaÅ¥ log. Skontrolujte to, prosÃm, na Geocaching.com.</string> - <string name="err_log_post_failed_ec">c:geo pravdepodobne nemohlo odoslaÅ¥ log. Skontrolujte to, prosÃm, na Extremcaching.com.</string> - <string name="err_logimage_post_failed">Obrázok k logu sa pravdepodobne nepodarilo nahraÅ¥. Skontrolujte to, prosÃm, na Geocaching.com.</string> + <string name="err_log_post_failed">Zdá sa že tvoj log nebol uverejnený. Skontroluj to na stránke keÅ¡e.</string> + <string name="err_logimage_post_failed">Zdá sa že obrázok logu nebol nahratý. Skontroluj to na stránke keÅ¡e.</string> <string name="err_search_address_forgot">c:geo zabudlo adresu, ktorú sa pokúšate nájsÅ¥.</string> <string name="err_parse_lat">c:geo nemôže zistiÅ¥ zemepisnú Å¡Ãrku.</string> <string name="err_parse_lon">c:geo nemôže dopoÄÃtaÅ¥ zemepisnú dĺžku.</string> @@ -211,6 +212,7 @@ <string name="loc_net">sieÅ¥</string> <string name="loc_fused">ZlúÄené</string> <string name="loc_low_power">NÃzka spotreba</string> + <string name="loc_home">Súradnice domova</string> <string name="loc_gps">GPS</string> <string name="loc_sat">sat</string> <string name="loc_trying">zisÅ¥ovanie polohy</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">V okolÃ</string> <string name="advanced_search_button">Hľadanie</string> <string name="stored_caches_button">Uložené</string> - <string name="any_button">Ciele</string> + <string name="any_button">ChoÄ k</string> <string name="unknown_scan">Nepodarilo sa nájsÅ¥ geokód v naÄÃtanom výsledku.</string> <string name="caches_no_cache">Žiadne skrýše</string> <string name="caches_more_caches">NaÄÃtaÅ¥ ÄalÅ¡ie skrýše</string> @@ -259,15 +261,24 @@ <string name="caches_sort_finds">poÄtu nájdenÃ</string> <string name="caches_sort_state">stavu</string> <string name="caches_sort_storage">dátumu uloženia v zariadenÃ</string> + <string name="caches_sort_eventdate">Dátum Eventu</string> <string name="caches_select_mode">Mód výberu</string> <string name="caches_select_mode_exit">OpustiÅ¥ mód výberu</string> <string name="caches_select_invert">Inverzný výber</string> <string name="caches_nearby">V okolÃ</string> <string name="caches_manage">SpravovaÅ¥</string> <string name="caches_remove_all">OdstrániÅ¥ vÅ¡etky</string> - <string name="caches_remove_all_confirm">Chcete odstrániÅ¥ vÅ¡etky %s skrýše z aktuálneho zoznamu?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Chcete odstrániÅ¥ túto skrýšu z tohoto zoznamu?</item> + <item quantity="few">Chcete odstrániÅ¥ tieto %d skrýše z tohoto zoznamu?</item> + <item quantity="other">Chcete odstrániÅ¥ týchto %d skrýš z tohoto zoznamu?</item> + </plurals> <string name="caches_remove_selected">OdstrániÅ¥ vybraté</string> - <string name="caches_remove_selected_confirm">Chcete odstrániÅ¥ %s vybraté skrýše z vášho zariadenia?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Chcete odstrániÅ¥ túto skrýšu zo zariadenia?</item> + <item quantity="few">Chcete odstrániÅ¥ tieto %d skrýše zo zariadenia?</item> + <item quantity="other">Chcete odstrániÅ¥ týchto %d skrýš zo zariadenia?</item> + </plurals> <string name="caches_remove_progress">Odstraňovanie skrýše</string> <string name="caches_delete_events">OdstrániÅ¥ minulé Eventy</string> <string name="caches_refresh_selected">ObnoviÅ¥ vybraté</string> @@ -287,13 +298,18 @@ <string name="caches_filter_track">S trasovateľnými predmetmi</string> <string name="caches_filter_clear">Bez filtrovania</string> <string name="caches_filter_modified">S upravenými súradnicami</string> + <string name="caches_filter_offline_log">S offline logmi</string> <string name="caches_filter_origin">Pôvod</string> <string name="caches_filter_distance">VzdialenosÅ¥</string> <string name="caches_filter_personal_note">S osobnou poznámkou</string> <string name="caches_filter_popularity">Obľúbené</string> <string name="caches_filter_popularity_ratio">Obľúbené [%]</string> + <string name="caches_filter_personal_data">S osobnými údajmi</string> + <string name="caches_filter_rating">S hodnotenÃm</string> + <string name="caches_filter_own_rating">S vlastným hodnotenÃm</string> <string name="caches_removing_from_history">Odstraňovanie z histórie…</string> <string name="caches_clear_offlinelogs">VymazaÅ¥ offline záznamy</string> + <string name="caches_clear_offlinelogs_message">Prajete si vymazaÅ¥ offline logy?</string> <string name="caches_clear_offlinelogs_progress">Vymazanie logov v režime offline</string> <string name="list_menu_create">VytvoriÅ¥ nový zoznam</string> <string name="list_menu_drop">OdstrániÅ¥ tento zoznam</string> @@ -316,13 +332,17 @@ <string name="list_not_available">Zoznam nie je k dispozÃcii, prechod na Å¡tandardný zoznam</string> <string name="about_version">Verzia</string> <string name="about_changelog">Zmeny</string> + <string name="about_system">Systém</string> <string name="about_donate">Podpora vývoja</string> <string name="about_donation_more">Podporte\nvývoj</string> <string name="about_contributors">Prispievatelia</string> <string name="about_license">Licencia</string> <string name="about_apache_license"><a href=""> Apache License, verzia 2.0</a></string> <string name="about_help">Pomoc</string> + <string name="about_system_include">KeÄ budete posielaÅ¥ správu o chybe alebo budete chcieÅ¥ vedieÅ¥ viac o c:geo, uveÄte, prosÃm, nasledujúce systémové informácie:</string> + <string name="changelog_github">Zoznam vÅ¡etkých zmien</string> <string name="settings_title_services">Služby</string> + <string name="settings_summary_services">KonfigurovaÅ¥ informácie o použÃvateľskom konte a prÃstup k voliteľným službám.</string> <string name="settings_title_appearance">Vzhľad</string> <string name="settings_title_cachedetails">Detaily skrýše</string> <string name="settings_title_offlinedata">Údaje v režime offline</string> @@ -370,6 +390,9 @@ <string name="settings_activate_oc_uk">AktivovaÅ¥</string> <string name="init_oc_uk_description">AutorizovaÅ¥ c:geo pre opencaching.org.uk na vyhľadávanie, zobrazenie a filtrovanie nájdených skrýš.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">Ak chcete hodnotiÅ¥ keÅ¡e, postupujte podľa pokynov na GCVote.com a potom sem zadajte svoje GCVote heslo.</string> + <string name="err_gcvote_send_rating">Chyba pri odosielanà hodnotenia, skontrolujte GCVote heslo v nastaveniach alebo ho ponechajte prázdne.</string> + <string name="gcvote_sent">Hlasovanie úspeÅ¡ne odoslané</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">AktivovaÅ¥</string> <string name="init_username">použÃvateľské meno</string> @@ -440,6 +463,8 @@ <string name="init_backup_success">Databáza c:geo bola úspeÅ¡ne skopÃrovaná do:</string> <string name="init_backup_failed">Záloha databázy c:geo zlyhala.</string> <string name="init_backup_unnecessary">Databáza je prázdna, záloha nie je potrebná.</string> + <string name="backup_confirm_overwrite">Naozaj chceÅ¡ prepÃsaÅ¥ existujúcu zálohu z %s?</string> + <string name="restore_confirm_overwrite">Naozaj chceÅ¡ prepÃsaÅ¥ %s na tvojom zariadenà zálohou?</string> <string name="init_restore_success">ÚspeÅ¡ne obnovené.</string> <string name="init_restore_failed">Obnova zlyhala.</string> <string name="init_restore_running">Obnovovanie databázy skrýš…</string> @@ -599,6 +624,7 @@ </plurals> <string name="cache_waypoints_add">PridaÅ¥ bod</string> <string name="cache_hint">Nápoveda</string> + <string name="cache_hint_not_available">Žiadna nápoveda</string> <string name="cache_logs">Logbook</string> <string name="cache_logs_friends_and_own">Logy priateľov/vlastné</string> <string name="cache_dialog_loading_details">NaÄÃtanie detailov skrýše…</string> @@ -637,10 +663,11 @@ <string name="cache_menu_map_ext">ZobraziÅ¥ na externej mape</string> <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">OtvoriÅ¥ v prehliadaÄi</string> - <string name="cache_menu_visit">ZapÃsaÅ¥ návÅ¡tevu</string> - <string name="cache_menu_visit_offline">ZapÃsaÅ¥ návÅ¡evu offline</string> + <string name="cache_menu_visit">ZalogovaÅ¥ návÅ¡tevu</string> + <string name="cache_menu_visit_offline">ZalogovaÅ¥ offline</string> <string name="cache_menu_spoilers">Obrázky s nápovedou</string> <string name="cache_menu_around">Skrýše v okolÃ</string> + <string name="around">Okolo %s</string> <string name="cache_menu_event">PridaÅ¥ do kalendára</string> <string name="cache_menu_details">Detaily</string> <string name="cache_menu_refresh">ObnoviÅ¥</string> @@ -650,6 +677,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_vote">HlasovaÅ¥</string> + <string name="cache_menu_checker">OtvoriÅ¥ Geochecker</string> + <string name="cache_menu_ignore">IgnorovaÅ¥ keÅ¡</string> <string name="cache_status">Stav</string> <string name="cache_status_offline_log">Uložený log</string> <string name="cache_status_found">Nájdená</string> @@ -735,6 +765,7 @@ <string name="waypoint_note">poznámka</string> <string name="waypoint_visited">navÅ¡tÃvený</string> <string name="waypoint_save">UložiÅ¥</string> + <string name="waypoint_cancel_edit">ZruÅ¡iÅ¥</string> <string name="waypoint_loading">NaÄÃtanie bodu trasy…</string> <string name="waypoint_do_not_touch_cache_coordinates">Bez zmeny súradnÃc skrýše</string> <string name="waypoint_set_as_cache_coords">NastaviÅ¥ ako súradnice skrýše v c:geo</string> @@ -759,6 +790,8 @@ <string name="search_clear_history">ZmazaÅ¥ históriu</string> <string name="search_history_cleared">História zmazaná</string> <string name="waypoint_coordinate_formats_plain">Iba text</string> + <string name="from_clipboard">Zo schránky</string> + <string name="copy_to_clipboard">KopÃrovaÅ¥ do schránky</string> <string name="visit_tweet">InformovaÅ¥ o nájdenà na Twitteri</string> <string name="map_map">Mapa</string> <string name="map_live">AktÃvna mapa</string> @@ -863,7 +896,7 @@ <string name="helper_contacts_description">Umožňuje otvorenie karty kontaktu (z adresára) priamo z logbooku, takže môžete ľahko požiadaÅ¥ priateľov o pomoc.</string> <string name="helper_sendtocgeo_description">PoslaÅ¥ do c:geo je rozÅ¡Ãrenie prehliadaÄa <strong>pre vaÅ¡e PC</strong>. Pri browsovanà geocaching.com, môžete poslaÅ¥ cache do vášho smartphone kliknutÃm na tlaÄidlo priamo v prehliadaÄi.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">UžitoÄná aplikácia zobrazujúca Online i Offline mapy a umožňujúca ich stiahnutie priamo do Offline režimu (iba rastrové online mapy). Tiež podporuje nahrávanie trasy, správu bodov záujmu (POI) a mnoho iných užitoÄných funkciÃ.</string> + <string name="helper_locus_description">NavigaÄná aplikácia pre tvoj mobil alebo tablet. Zmapuj okolie cez offline topografické mapy, zaznamenávaj svoju cestu, hľadaj geocache, použÃvaj hlasovú navigáciu a rob eÅ¡te oveľa viac.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Radar z tejto aplikácie môžete použiÅ¥ v c:geo. Poskytuje tiež mnoho iných informácià súvisiacich s GPS.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -889,8 +922,8 @@ <string name="export_gpx">GPX</string> <string name="export_gpx_info">Súbor GPX bude exportovaný do %1$s s názvom súboru podľa aktuálneho dátumu a Äasu.</string> <string name="export_gpx_to">OdoslaÅ¥ exportovaný GPX súbor do</string> - <string name="attribute_dogs_yes">Psi povolené</string> - <string name="attribute_dogs_no">Psi nepovolené</string> + <string name="attribute_dogs_yes">Psy povolené</string> + <string name="attribute_dogs_no">Psy nepovolené</string> <string name="attribute_bicycles_yes">Bicykle povolené</string> <string name="attribute_bicycles_no">Bicykle nepovolené</string> <string name="attribute_motorcycles_yes">Motorky povolené</string> @@ -1115,13 +1148,15 @@ <string name="attribute_offset_cache_no">Nie je offset cache</string> <string name="quote">Pre jednoduchÅ¡ie hľadanie skrýš a použÃvateľov lenivÅ¡Ãch.</string> <string name="powered_by">carnero</string> - <string name="support">Podpora: <a href="">support@cgeo.org</a></string> - <string name="website">Web: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href=""> c:geo na Google Play</a></string> + <string name="support_title">Podpora</string> + <string name="website_title">Webová stránka</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">stránka c:geo</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo na Google Play</a></string> <string name="about_twitter">Chcete, aby <b>c:geo</b> napÃsalo na váš Twitter vždy, keÄ zapÃÅ¡ete nájdenie skrýše?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Je dostupné nové vydanie.\nKliknite pre inÅ¡taláciu.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Je dostupná nová noÄná zostava.\nKliknite pre inÅ¡taláciu.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Je dostupná nová verzia „release candidate“.\nKliknite pre inÅ¡taláciu.</string> @@ -1172,7 +1207,7 @@ <item quantity="few">%s obľúbené</item> <item quantity="other">%s obľúbených</item> </plurals> - <string name="percent_favorite_points">% \ obľúbených</string> + <string name="more_than_percent_favorite_points">> %d %% obľúbených</string> <string name="cgeo_shortcut">c:Geo odkaz</string> <string name="create_shortcut">VytvoriÅ¥ odkaz</string> <string name="send">OdoslaÅ¥</string> @@ -1182,6 +1217,8 @@ <string name="showcase_main_text">c:geo teraz umiestňuje položky menu v záhlavÃ, ako iné moderné aplikácie. Niektoré položky sú skryté za symbolom bodiek. Dlhým podržanÃm tlaÄidla sa zobrazà jeho popis.</string> <string name="showcase_cachelist_title">PrepÃnanie zoznamov</string> <string name="showcase_cachelist_text">Môžete prepÃnaÅ¥ medzi svojimi zoznamami skrýš kliknutÃm na názov zoznamu.</string> + <string name="showcase_compass_hint_title">ZobraziÅ¥ nápovedu</string> + <string name="showcase_compass_hint_text">Táto vec ti môže pomôcÅ¥ pri hľadanà skrýše - zobrazà nápovedu ak je dostupná.</string> <string name="confirm_log_title">NezvyÄajný typ logu</string> <string name="confirm_log_message">ChceÅ¡ zalogovaÅ¥ \'%s\'. UrÄite?</string> </resources> diff --git a/main/res/values-sl/strings.xml b/main/res/values-sl/strings.xml index b6cd540..65fe770 100644 --- a/main/res/values-sl/strings.xml +++ b/main/res/values-sl/strings.xml @@ -74,7 +74,6 @@ <string name="log_tb_visit">Obisk</string> <string name="log_tb_drop">Pusti v zakladu</string> <string name="log_tb_changeall">Spremeni vse</string> - <string name="log_save">Shrani</string> <string name="log_saving">PoÅ¡iljam…</string> <string name="log_saving_and_uploading">PoÅ¡iljam zapis in nalagam sliko…</string> <string name="log_clear">PoÄisti</string> @@ -158,7 +157,6 @@ <string name="err_acquire_image_failed">Pridobivanje slike ni uspelo.</string> <string name="err_tb_display">c:geo ne more prikazati željenega sledljivÄka. Ali je res sledljivÄek?</string> <string name="err_tb_details_open">c:geo ne more pokazati podatke sledljivÄka.</string> - <string name="err_tb_forgot_saw">c:geo je pozabil kateri sledljivÄek hoÄete.</string> <string name="err_tb_find">c:geo ni naÅ¡el sledljivÄka.</string> <string name="err_tb_find_that">c:geo ni naÅ¡el tega sledljivÄka.</string> <string name="err_waypoint_cache_unknown">c:geo ne ve h kateremu zakladu želite dodati toÄko.</string> @@ -166,15 +164,11 @@ <string name="err_point_unknown_position">c:geo ne ve kje ste.</string> <string name="err_point_no_position_given_title">Potrebne informacije</string> <string name="err_point_no_position_given">Vnesite vsaj koordinate ali pa razdaljo in smer. Izpolnete lahko tudi vsa polja.</string> - <string name="err_point_curr_position_unavailable">c:geo Å¡e vedno nima trenutnih koordinat. Prosimo poÄakajte…</string> <string name="err_point_bear_and_dist_title">Potrebujete pomoÄ?</string> <string name="err_point_bear_and_dist">Vnesite smer in razdaljo. Smer je kot med 0 in 360 stopinjami od severa. Razdalja je lahko z ali brez enot.</string> <string name="err_log_load_data">c:geo ni mogel naložiti podatkov za zapis obiska.</string> <string name="err_log_load_data_again">c:geo ne more naložiti podatkov za zapis obiska. Ponovni poskus…</string> <string name="err_log_load_data_still">c:geo Å¡e vedno nalaga podatke za zapis obiska. Prosimo poÄakajte Å¡e trenutek.</string> - <string name="err_log_post_failed">Izgleda, kot da zapis ni bil objavljen. Preverite na Geocaching.com.</string> - <string name="err_log_post_failed_ec">Izgleda, da vaÅ¡ zapis ni bil objavljen. Preverite na Extremcaching.com.</string> - <string name="err_logimage_post_failed">Izgleda, kot da slika ni bila naložena. Preverite na Geocaching.com.</string> <string name="err_search_address_forgot">c:geo je pozabil naslov, ki ste ga hoteli najti.</string> <string name="err_parse_lat">c:geo ni razumel geografske Å¡irine.</string> <string name="err_parse_lon">c:geo ni razumel geografske dolžine.</string> @@ -229,7 +223,6 @@ <string name="caches_nearby_button">V bližini</string> <string name="advanced_search_button">Iskanje</string> <string name="stored_caches_button">Shranjeni</string> - <string name="any_button">Destinacije</string> <string name="unknown_scan">Iskanje žal ni obrodilo sadov.</string> <string name="caches_no_cache">Ni zakladov</string> <string name="caches_more_caches">Naloži veÄ zakladov</string> @@ -271,9 +264,7 @@ <string name="caches_nearby">V bližini</string> <string name="caches_manage">Upravljaj</string> <string name="caches_remove_all">Odstrani vse</string> - <string name="caches_remove_all_confirm">Ali želite odstraniti vseh %s zakladov iz trenutnega seznama?</string> <string name="caches_remove_selected">Odstrani izbrane</string> - <string name="caches_remove_selected_confirm">Ali želite odstraniti %s oznaÄenih zakladov iz vaÅ¡e naprave?</string> <string name="caches_remove_progress">Odstranjujem zaklade</string> <string name="caches_delete_events">IzbriÅ¡i pretekla sreÄanja</string> <string name="caches_refresh_selected">Osveži izbrane</string> @@ -643,7 +634,6 @@ <string name="cache_menu_streetview">Pogled ulic</string> <string name="cache_menu_browser">Odpri v brskalniku</string> <string name="cache_menu_visit">Objavi zapis</string> - <string name="cache_menu_visit_offline">Shrani zapis</string> <string name="cache_menu_spoilers">Spoiler slike</string> <string name="cache_menu_around">Zakladi v bližini</string> <string name="cache_menu_event">Dodaj na koledar</string> @@ -868,7 +858,6 @@ <string name="helper_contacts_description">OmogoÄa vam odpiranje vizitke kontakta (v vaÅ¡em adresarju) direktno iz zapisa, tako da lahko lažje vpraÅ¡ate prijatelje za pomoÄ.</string> <string name="helper_sendtocgeo_description">Send to c:geo je razÅ¡iritev za vaÅ¡ brskalnik <strong>na vaÅ¡em raÄunalniku</strong>. Ko brskate na geocaching.com, lahko iz spletne strani poÅ¡ljete zaklad direktno na vaÅ¡o napravo s klikom na gumb znotraj brskalnika.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Aplikacija Locus vam omogoÄa prikaz zemljevidov brez povezave in prenos zemljevidov direktno na napravo (samo rasterski zemljevidi). OmogoÄa tudi beleženje lokacije, uporavljanje s toÄkami zanimivosti in drugimi uporabnimi funkcionalnostmi.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Aplikacija GPS Status vam omogoÄa prikaz radarja in uporabljate jo lahko z aplikacijo c:geo. OmogoÄa tudi prikaz veliko drugih informacij povezanih z GPS in njihovimi orodji.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1120,13 +1109,7 @@ <string name="attribute_offset_cache_no">Ni Offset zaklad</string> <string name="quote">Za lažji geocaching in bolj lene zakladolovce.</string> <string name="powered_by">carnero</string> - <string name="support">Podpora: <a href="">support@cgeo.org</a></string> - <string name="website">Spletna stran: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo stran</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo na Google Play</a></string> <string name="about_twitter">Naj <b>c:geo</b> objavi nov status na Twitter, ko objavite nov zapis pri zakladu?</string> - <string name="faq">Pogosto zastavljena vpraÅ¡anja: <a href="">faq.cgeo.org</a></string> <string name="status_new_release" tools:ignore="UnusedResources">Na voljo je nova razliÄica.\nKliknite za namestitev.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Na voljo je nova dnevna razliÄica.\nKliknite za namestitev.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Na voljo je nova preizkusna razliÄica.\nKliknite za namestitev.</string> @@ -1183,7 +1166,6 @@ <item quantity="few">%s favoritov</item> <item quantity="other">%s favoritov</item> </plurals> - <string name="percent_favorite_points">%\ favoritov</string> <string name="cgeo_shortcut">Bližnjica c:geo</string> <string name="create_shortcut">Ustvari bližnjico</string> <string name="send">PoÅ¡lji</string> diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml index e32e45a..3ed622f 100644 --- a/main/res/values-sv/strings.xml +++ b/main/res/values-sv/strings.xml @@ -17,7 +17,7 @@ <string name="letterbox">Letterbox hybrid</string> <string name="event">Event cache</string> <string name="mega">Mega-event cache</string> - <string name="giga">Giga-Event Cache</string> + <string name="giga">Giga-Event cache</string> <string name="earth">Earthcache</string> <string name="cito">Cache in trash out event</string> <string name="webcam">Webcam cache</string> @@ -74,12 +74,14 @@ <string name="log_tb_visit">Besök</string> <string name="log_tb_drop">Lämna här</string> <string name="log_tb_changeall">Ändra alla</string> - <string name="log_save">Spara</string> + <string name="log_save">Spara offline</string> <string name="log_saving">Sparar logg…</string> <string name="log_saving_and_uploading">Sparar logg och laddar upp bild…</string> <string name="log_clear">Rensa</string> <string name="log_post_not_possible">Laddar loggningssida…</string> + <string name="log_date_future_not_allowed">Framtida loggdatum är inte tillÃ¥tna.</string> <string name="log_add">Lägg till</string> + <string name="log_repeat">Upprepa senaste loggen</string> <string name="log_no_rating">Inget betyg</string> <string name="log_stars_1_description">DÃ¥lig</string> <string name="log_stars_15_description">HalvdÃ¥lig</string> @@ -107,6 +109,7 @@ <string name="log_password_title">Logglösenord:</string> <string name="log_hint_log_password">Ange ditt lösenord för loggning</string> <string name="log_oc_team_comment">Meddelande frÃ¥n OC Team</string> + <string name="log_your_saved_log">Din sparade logg</string> <string-array name="log_image_scales"> <item>Ingen skalning</item> <item>512 px</item> @@ -124,6 +127,7 @@ <string name="err_login">Inloggningsinformationen ej sparad</string> <string name="err_login_failed_toast">Tyvärr kan c:geo inte logga in. c:geo kommer att köra i offline läge med sparade cacher. Kontrollera dina inloggningsuppgifter och aktivera din internetanslutning.</string> <string name="err_unknown">Okänt fel</string> + <string name="err_unknown_address">c:geo kunde inte associera adressen till en plats</string> <string name="err_comm">Okänt kommunikationsfel</string> <string name="err_missing_auth">Användarnamn och/eller lösenord saknas.</string> <string name="err_wrong">Felaktiga inloggningsuppgifter</string> @@ -158,7 +162,6 @@ <string name="err_acquire_image_failed">Hämtning av bilden misslyckades.</string> <string name="err_tb_display">Tyvärr kan c:geo inte visa den trackable du önskar. Är den verkligen trackable?</string> <string name="err_tb_details_open">Tyvärr kan c:geo inte öppna detaljer för trackable.</string> - <string name="err_tb_forgot_saw">Tyvärr glömde c:geo vilken trackable du sÃ¥g.</string> <string name="err_tb_find">Tyvärr kunde c:geo inte hitta trackable</string> <string name="err_tb_find_that">Tyvärr kan c:geo inte hitta önskad trackable.</string> <string name="err_waypoint_cache_unknown">Tyvärr vet inte c:geo till vilken cache du vill lägga till en punkt.</string> @@ -166,15 +169,13 @@ <string name="err_point_unknown_position">Tyvärr kan c:geo inte bestämma din position.</string> <string name="err_point_no_position_given_title">Mer info krävs</string> <string name="err_point_no_position_given">Ange minst latitud och longitud eller avstÃ¥nd och riktning. Du kan ocksÃ¥ ange alla fyra.</string> - <string name="err_point_curr_position_unavailable">c:geo har ännu inte nuvarande koordinater. Vänta en stund…</string> <string name="err_point_bear_and_dist_title">Tips!</string> <string name="err_point_bear_and_dist">Ange bÃ¥de riktning och avstÃ¥nd. Rikting är en vinkel mellan 0 och 360 grader relativt norr. AvstÃ¥nd anges med eller utan enhet.</string> <string name="err_log_load_data">Tyvärr kan c:geo inte ladda information som krävs för att logga ditt besök.</string> <string name="err_log_load_data_again">Tyvärr kan c:geo inte ladda information som krävs för att logga ditt besök. Försöker igen.</string> <string name="err_log_load_data_still">c:geo laddar fortfarande data för att kunna posta loggen. Vänligen vänta en stund till.</string> - <string name="err_log_post_failed">Tyvärr misslyckades c:geo att posta loggen.</string> - <string name="err_log_post_failed_ec">Det verkar som att din logg inte kunde laddas upp. Kontrollera loggen pÃ¥ Extremcaching.com.</string> - <string name="err_logimage_post_failed">Det verkar som om din bild till loggen inte kunde laddas upp. Vänligen kontrollera den pÃ¥ Geocaching.com.</string> + <string name="err_log_post_failed">Det verkar som att din logg inte kunde postas. Kontrollera loggen pÃ¥ cachens ursprungliga hemsida.</string> + <string name="err_logimage_post_failed">Det verkar som att din logg bild inte kunde laddas upp. Kontrollera bilden pÃ¥ cachens hemsida.</string> <string name="err_search_address_forgot">Tyvärr glömde c:geo adressen du sökte efter.</string> <string name="err_parse_lat">Tyvärr kan c:geo inte tolka latitud.</string> <string name="err_parse_lon">Tyvärr kan c:geo inte tolka longitud.</string> @@ -211,6 +212,7 @@ <string name="loc_net">Nätverk</string> <string name="loc_fused">Kombinerad</string> <string name="loc_low_power">Strömspar</string> + <string name="loc_home">Hemkoordinater</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Försöker hitta plats</string> @@ -229,7 +231,7 @@ <string name="caches_nearby_button">Nära</string> <string name="advanced_search_button">Sök</string> <string name="stored_caches_button">Sparade</string> - <string name="any_button">Valfritt mÃ¥l</string> + <string name="any_button">GÃ¥ till</string> <string name="unknown_scan">Hittade inte nÃ¥gon geokod i scanningen.</string> <string name="caches_no_cache">Det finns ingen cache</string> <string name="caches_more_caches">Ladda fler cacher</string> @@ -263,15 +265,18 @@ <string name="caches_sort_finds">Antal som hittat</string> <string name="caches_sort_state">Status</string> <string name="caches_sort_storage">Tid för sparandet i enheten</string> + <string name="caches_sort_eventdate">Eventdatum</string> <string name="caches_select_mode">Markeringsläge</string> <string name="caches_select_mode_exit">Avsluta markeringsläge</string> <string name="caches_select_invert">Invertera valda</string> <string name="caches_nearby">Nära</string> <string name="caches_manage">Hantera</string> <string name="caches_remove_all">Ta bort alla</string> - <string name="caches_remove_all_confirm">Vill du ta bort alla %s cacher frÃ¥n denna lista?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Vill du radera denna cachen frÃ¥n den här listan?</item> + <item quantity="other">Vill du radera dessa %d cacher frÃ¥n den här listan?</item> + </plurals> <string name="caches_remove_selected">Ta bort valda</string> - <string name="caches_remove_selected_confirm">Vill du ta bort de %s markerade cacherna frÃ¥n enheten?</string> <string name="caches_remove_progress">Tar bort cacher</string> <string name="caches_delete_events">Ta bort gamla event</string> <string name="caches_refresh_selected">Uppdatera valda</string> @@ -291,13 +296,18 @@ <string name="caches_filter_track">Med trackables</string> <string name="caches_filter_clear">Rensa filter</string> <string name="caches_filter_modified">Med tillagda koordinater</string> + <string name="caches_filter_offline_log">Med offlinelogg</string> <string name="caches_filter_origin">Ursprung</string> <string name="caches_filter_distance">AvstÃ¥nd</string> <string name="caches_filter_personal_note">Med personlig anteckning</string> <string name="caches_filter_popularity">Favoriter</string> <string name="caches_filter_popularity_ratio">Favoriter [%]</string> + <string name="caches_filter_personal_data">Med personlig info</string> + <string name="caches_filter_rating">Med betyg</string> + <string name="caches_filter_own_rating">Med eget betyg</string> <string name="caches_removing_from_history">Tar bort frÃ¥n historik…</string> <string name="caches_clear_offlinelogs">Rensa offline loggar</string> + <string name="caches_clear_offlinelogs_message">Vill du rensa offline loggarna?</string> <string name="caches_clear_offlinelogs_progress">Rensar offline loggar</string> <string name="list_menu_create">Skapa en ny lista</string> <string name="list_menu_drop">Ta bort den här listan</string> @@ -320,13 +330,17 @@ <string name="list_not_available">Listan är inte längre tillgänglig, byter till standardlistan</string> <string name="about_version">Version</string> <string name="about_changelog">Historik</string> + <string name="about_system">System</string> <string name="about_donate">Stöd c:geo</string> <string name="about_donation_more">Donera till\nutveckling</string> <string name="about_contributors">Medarbetare</string> <string name="about_license">Licens</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Hjälp</string> + <string name="about_system_include">Vänligen inkludera följande systeminformation när du skickar en felrapport eller ber om mer information om c:geo:</string> + <string name="changelog_github">Lista över alla ändringar</string> <string name="settings_title_services">Tjänster</string> + <string name="settings_summary_services">Ställ in kontoinformation och tillgÃ¥ng till valbara tjänster.</string> <string name="settings_title_appearance">Utseende</string> <string name="settings_title_cachedetails">Cachedetaljer</string> <string name="settings_title_offlinedata">Offlinedata</string> @@ -374,6 +388,9 @@ <string name="settings_activate_oc_uk">Aktivera</string> <string name="init_oc_uk_description">Använd c:geo med opencaching.org.uk för att söka efter cacher samt för att filtrera dina funna cacher.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">För att kunna betygsätta en cache mÃ¥ste du följa instruktionerna pÃ¥ GCVote.com och ange ditt lösenord till GCVote här.</string> + <string name="err_gcvote_send_rating">Fel uppstod när betyg skulle sparas, kontrollera eller ta bort lösenordet för GCVote i inställningarna.</string> + <string name="gcvote_sent">Röst skickades</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Aktivera</string> <string name="init_username">Användare</string> @@ -444,6 +461,8 @@ <string name="init_backup_success">Databasen som används av c:geo har kopierats till filen</string> <string name="init_backup_failed">Kopieringen av c:geos databas misslyckades.</string> <string name="init_backup_unnecessary">Databasen är tom, säkerhetkopiering behövs inte.</string> + <string name="backup_confirm_overwrite">Vill du skriva över den befintliga säkerhetskopian frÃ¥n %s?</string> + <string name="restore_confirm_overwrite">Vill du skriva över %s pÃ¥ enheten med säkerhetskopian?</string> <string name="init_restore_success">Ã…terställning klar.</string> <string name="init_restore_failed">Ã…terställningen misslyckades.</string> <string name="init_restore_running">Ã…terställer databasen med cacher…</string> @@ -606,6 +625,7 @@ </plurals> <string name="cache_waypoints_add">Lägg till punkt</string> <string name="cache_hint">Tips</string> + <string name="cache_hint_not_available">Ingen ledtrÃ¥d tillgänglig</string> <string name="cache_logs">Loggbok</string> <string name="cache_logs_friends_and_own">Vänners/egna loggar</string> <string name="cache_dialog_loading_details">Laddar detaljer om cachen…</string> @@ -645,9 +665,10 @@ <string name="cache_menu_streetview">Gatuvy</string> <string name="cache_menu_browser">Öppna i webbläsare</string> <string name="cache_menu_visit">Logga besök</string> - <string name="cache_menu_visit_offline">Logga besök offline</string> + <string name="cache_menu_visit_offline">Snabblogga offline</string> <string name="cache_menu_spoilers">Spoiler bilder</string> <string name="cache_menu_around">Cacher i närheten</string> + <string name="around">Kring %s</string> <string name="cache_menu_event">Lägg till i kalender</string> <string name="cache_menu_details">Detaljer</string> <string name="cache_menu_refresh">Uppdatera</string> @@ -657,6 +678,9 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_android_wear">Android Wear</string> + <string name="cache_menu_vote">Rösta</string> + <string name="cache_menu_ignore">Ignorera cache</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Sparad logg</string> <string name="cache_status_found">Hittad</string> @@ -766,6 +790,8 @@ <string name="search_clear_history">Rensa historik</string> <string name="search_history_cleared">Historiken rensad</string> <string name="waypoint_coordinate_formats_plain">Standard</string> + <string name="from_clipboard">FrÃ¥n Urklipp</string> + <string name="copy_to_clipboard">Kopiera till urklipp</string> <string name="visit_tweet">Skicka att du hittat till Twitter</string> <string name="map_map">Karta</string> <string name="map_live">Live karta</string> @@ -870,7 +896,7 @@ <string name="helper_contacts_description">Gör det möjligt att öppna en kontakt (i telefonens adressbok) direkt frÃ¥n en logg, sÃ¥ att du enkelt kan kontakta vänner för att fÃ¥ hjälp.</string> <string name="helper_sendtocgeo_description">Skicka till c:geo är ett tillägg till webbläsaren <strong>för din PC</strong>. När du bläddrar geocaching.com, kan du skicka cacher till din telefon med en knapptryckning i webbläsaren.</string> <string name="helper_locus_title">Locus</string> - <string name="helper_locus_description">Ett enkelt program för att visa Online kartor men som ocksÃ¥ medger nedladdning av raster kartor för användning i Offline läge. Stödjer även inspelning av väg (track recording), POI hantering och mÃ¥nga andra användbara funktioner.</string> + <string name="helper_locus_description">App för navigering utomhus med telefon eller tablet. Visa topo-kartor offline, spÃ¥ra din rutt, leta geocacher, använd guideröst och mycket mer.</string> <string name="helper_gpsstatus_title">GPS Status</string> <string name="helper_gpsstatus_description">Erbjuder mÃ¥nga GPS-relaterade funktioner. Radar-funktionen i detta program kan användas i c:geo.</string> <string name="helper_bluetoothgps_title">Bluetooth GPS</string> @@ -1122,13 +1148,15 @@ <string name="attribute_offset_cache_no">Ingen offset cache</string> <string name="quote">To make geocaching easier, to make users lazier.</string> <string name="powered_by">carnero</string> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Hemsida: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo pÃ¥ Google Play</a></string> + <string name="support_title">Support</string> + <string name="website_title">Webbsida</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">c:geo pÃ¥ Facebook</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo pÃ¥ Google Play</a></string> <string name="about_twitter">Ska <b>c:geo</b> publicera ny status pÃ¥ Twitter varje gÃ¥ng en cache loggas?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <string name="status_new_release" tools:ignore="UnusedResources">Ny officiell version finns tillgänglig.\nKlicka för att installera.</string> <string name="status_new_nightly" tools:ignore="UnusedResources">Nytt nattligt bygge finns tillgängligt.\nKlicka för att installera.</string> <string name="status_new_rc" tools:ignore="UnusedResources">Ny kandidat till officiellt bygge finns tillgängligt.\nKlicka för att installera.</string> @@ -1169,11 +1197,11 @@ <item quantity="one">igÃ¥r</item> <item quantity="other">%d dagar sedan</item> </plurals> - <string name="percent_favorite_points">%\ favoriter</string> + <string name="more_than_percent_favorite_points">> %d%% favoriter</string> <string name="cgeo_shortcut">c:geo genväg</string> <string name="create_shortcut">Skapa genväg</string> <string name="send">Skicka</string> - <string name="showcase_logcache_title">Skickar loggen</string> + <string name="showcase_logcache_title">Skicka loggen</string> <string name="showcase_logcache_text">Kom ihÃ¥g, mÃ¥nga kommandon hittar du nu i titelraden. Där hittar du knappen för att skicka den avslutade loggen.</string> <string name="showcase_main_title">Nya menyer</string> <string name="showcase_main_text">c:geo placerar nu menyalternativ i titelraden likt andra moderna appar. NÃ¥gra alternativ döljs bakom symbolen med prickar. Tryck länge pÃ¥ en knapp för att se dess beskrivning.</string> diff --git a/main/res/values/changelog_release.xml b/main/res/values/changelog_release.xml index 364743a..e30807d 100644 --- a/main/res/values/changelog_release.xml +++ b/main/res/values/changelog_release.xml @@ -2,68 +2,11 @@ <resources> <!-- changelog for the release branch --> <string name="changelog_release" translatable="false">\n - <b>2014.09.18:</b>\n - · Fix: Hardware acceleration is unreliable on some devices\n - · Fix: Return correct error message if a cache is unpublished\n - · Fix: Better icon for navigation menu in cache details\n - · Fix: Reloading captcha was not working\n - · Fix: Minor layout corrections\n - · Fix: Avoid crashes after screen rotation\n + <b>next bugfix release</b>\n + · Fix: Wrong log count shown after logging something else than a found\n + · Fix: Copy to clipboard not possible on Android 5.1\n + · Fix: Cache links in Groundspeaks weekly mails not opening\n \n - <b>2014.09.02:</b>\n - · Fix: Hardware acceleration is unreliable on Android < 4.2 and on some devices\n - · Fix: Recognize new date formats on geocaching.com\n - · Fix: Date for event caches are not available in search results\n - · Fix: Favorite points should not be given to event caches\n - · Fix: Force English does not work on main screen\n - · Fix: Trackables are not included in search on main screen\n - · Fix: Trackables images are too small\n - · Fix: Default coordinates format for new installations should be degrees and decimal minutes\n - · Fix: Several non-frequent causes of crashes\n - \n - <b>2014.08.29:</b>\n - · Fix: Stored found or owned caches shown on map although set to hidden\n - \n - <b>2014.08.28:</b>\n - · New: Option to disable hardware acceleration on problematic devices\n - · Various bugfixes\n - \n - <b>2014.08.27a:</b>\n - \n - <font size="16"><b>IMPORTANT CHANGE</b></font>\n - · New: Actionbar menus (Long press action buttons for a description)\n - <a href="http://faq.cgeo.org/#10_83">Please do read our FAQ to learn more about the new menu!</a>\n - \n - · New: Show also own logs on friends log page\n - · New: Navigate - WhereYouGo will invoke automatic cartridge download in WhereYouGo\n - · New: Filter for caches which are not found\n - · New: Show \"Import from web\" also if not yet registered\n - · New: Popup list of changes on first start after upgrade\n - · New: Android Beam (NFC Sharing)\n - · New: Debugging option to save memory dumps on user demand\n - · New: Load Greokrety inventory for OC caches\n - · New: Autosave caches if user modifies waypoints\n - · New: Show recently viewed caches when clicking search icon on main screen\n - · New: Add support for opencaching.org.uk\n - · New: Improved sorting of waypoints depending on waypoint category\n - · New: Have a link to \"related webpage\" in cache details\n - · Fix: Hiding own caches on opencaching\n - · Fix: Webcam caches not marked as found after posting log\n - · Fix: Archived caches now also hidden if hiding disabled caches is active\n - · Fix: Filter invalid characters in GPX files\n - · Fix: All caches shown as owned if no username stored\n - · Fix: GPX import from mail failing on some devices\n - · Fix: Updating cache history should not ask for list to save caches\n - · Fix: Speed now always shown in km or miles per hour\n - · Fix: USER template now shows the correct username for the site where the cache is hosted\n - · Fix: Keep filter active if user switches the list\n - · Fix: Cache names with special chars not shown\n - · Fix: Improve static maps resolution and scaling depending on the screen resolution\n - · Fix: Will attend logs not counted in log summary of OC caches\n - · Fix: Improved loading of listing images\n - · Fix: Empty personal note not uploaded to gc.com\n - \n - <a href="https://github.com/cgeo/cgeo/issues?q=milestone%3A%22Next+feature+release%22+is%3Aclosed">Detailed list of all changes</a>\n \n <b>Known Limitations/Bugs:</b>\n · Device menu button not working on map popup\n diff --git a/main/res/values/dimens.xml b/main/res/values/dimens.xml index 9ef3b56..ab09412 100644 --- a/main/res/values/dimens.xml +++ b/main/res/values/dimens.xml @@ -5,4 +5,8 @@ <dimen name="actionbar_separator_height">37dip</dimen> <dimen name="actionbar_separator_width">2dip</dimen> + <!-- Dimensions for Samsung Multi-Window support --> + <dimen name="app_defaultsize_w">632.0dip</dimen> + <dimen name="app_defaultsize_h">598.0dip</dimen> + </resources>
\ No newline at end of file diff --git a/main/res/values/ids.xml b/main/res/values/ids.xml index e8cb74b..99a2311 100644 --- a/main/res/values/ids.xml +++ b/main/res/values/ids.xml @@ -24,6 +24,7 @@ <item name="cache_app_show_static_maps" type="id"/> <item name="cache_app_locus" type="id"/> <item name="cache_app_pebble" type="id"/> + <item name="cache_app_android_wear" type="id"/> <item name="cache_app_mapswithme" type="id"/> -</resources>
\ No newline at end of file +</resources> diff --git a/main/res/values/preference_keys.xml b/main/res/values/preference_keys.xml index e6ef67a..6335df3 100644 --- a/main/res/values/preference_keys.xml +++ b/main/res/values/preference_keys.xml @@ -49,7 +49,7 @@ <string name="pref_skin">skin</string> <string name="pref_showaddress">showaddress</string> <string name="pref_useenglish">useenglish</string> - <string name="pref_units">units</string> + <string name="pref_units_imperial">units</string> <string name="pref_autoloaddesc">autoloaddesc</string> <string name="pref_ratingwanted">ratingwanted</string> <string name="pref_friendlogswanted">friendlogswanted</string> @@ -92,6 +92,7 @@ <string name="pref_webDeviceCode">webDeviceCode</string> <string name="pref_maplive">maplive</string> <string name="pref_lastmapzoom">mapzoom</string> + <string name="pref_cache_zoom">cachezoom</string> <string name="pref_lastmaplat">maplat</string> <string name="pref_lastmaplon">maplon</string> <string name="pref_livelist">livelist</string> @@ -106,9 +107,10 @@ <string name="pref_coordinputformat">coordinputformat</string> <string name="pref_gccustomdate">gccustomdate</string> <string name="pref_cookiestore">cookiestore</string> + <string name="pref_googleplayservices">googleplayservices</string> + <string name="pref_lowpowermode">lowpowerlocation</string> <string name="pref_lastdetailspage">lastdetailspage</string> <string name="pref_livemapstrategy">livemapstrategy</string> - <string name="pref_hidelivemaphint">hidelivemaphint</string> <string name="pref_livemaphintshowcount">livemaphintshowcount</string> <string name="pref_settingsversion">settingsversion</string> <string name="pref_trackableaction">trackableaction</string> @@ -140,6 +142,7 @@ <string name="pref_navigation_menu_google_maps_directions">navigationMapsDirections</string> <string name="pref_navigation_menu_where_you_go">navigationWhereYouGo</string> <string name="pref_navigation_menu_pebble">navigationPebble</string> + <string name="pref_navigation_menu_android_wear">navigationAndroidWear</string> <string name="pref_navigation_menu_mapswithme">navigationMapsWithMe</string> <string name="pref_ocpl_tokensecret">ocpl_tokensecret</string> <string name="pref_ocpl_tokenpublic">ocpl_tokenpublic</string> @@ -180,4 +183,7 @@ <string name="pref_changelog_last_checksum">changelog_last_checksum</string> <string name="pref_caches_history">caches_history</string> <string name="pref_hardware_acceleration">hardware_acceleration2</string> + <string name="pref_last_cache_log">last_cache_log</string> + <string name="pref_last_trackable_log">last_trackable_log</string> + <string name="pref_home_location">home_location</string> </resources> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index b8c77a2..1d551e9 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -86,12 +86,14 @@ <string name="log_tb_visit">Visited</string> <string name="log_tb_drop">Dropped Off</string> <string name="log_tb_changeall">Change All</string> - <string name="log_save">Save</string> + <string name="log_save">Save offline</string> <string name="log_saving">Sending log…</string> <string name="log_saving_and_uploading">Sending log and uploading image…</string> <string name="log_clear">Clear</string> <string name="log_post_not_possible">Loading Log Page…</string> + <string name="log_date_future_not_allowed">Future log dates are not allowed.</string> <string name="log_add">Add</string> + <string name="log_repeat">Repeat last log</string> <string name="log_no_rating">No rating</string> <string name="log_stars_1_description">Poor</string> <string name="log_stars_15_description">Fairly poor</string> @@ -119,7 +121,8 @@ <string name="log_password_title">Log Password:</string> <string name="log_hint_log_password">Enter your log password</string> <string name="log_oc_team_comment">OC Team comment</string> - + <string name="log_your_saved_log">Your saved log</string> + <string-array name="log_image_scales"> <item>No scaling</item> <item>512 px</item> @@ -141,6 +144,7 @@ <string name="err_login">No Login information stored</string> <string name="err_login_failed_toast">c:geo can\'t log in. c:geo works offline with Stored caches. Check Login settings or enable your internet connection.</string> <string name="err_unknown">Unknown error</string> + <string name="err_unknown_address">c:geo was unable to map this address to an existing location</string> <string name="err_comm">Unknown communication error</string> <string name="err_missing_auth">No username and/or password set.</string> <string name="err_wrong">Login information incorrect</string> @@ -175,7 +179,6 @@ <string name="err_acquire_image_failed">Acquiring an image failed.</string> <string name="err_tb_display">c:geo can\'t display the trackable you want. Is it really a trackable?</string> <string name="err_tb_details_open">c:geo can\'t open trackable details.</string> - <string name="err_tb_forgot_saw">c:geo forgot which trackable you saw.</string> <string name="err_tb_find">c:geo can\'t find trackable</string> <string name="err_tb_find_that">c:geo can\'t find that trackable.</string> <string name="err_waypoint_cache_unknown">c:geo doesn\'t know to which cache you want to add a waypoint for.</string> @@ -183,15 +186,13 @@ <string name="err_point_unknown_position">c:geo can\'t recognize where you are.</string> <string name="err_point_no_position_given_title">Info required</string> <string name="err_point_no_position_given">Fill at least latitude and longitude or distance and bearing. You can also fill all four fields.</string> - <string name="err_point_curr_position_unavailable">c:geo still doesn\'t have current coordinates. Please, wait a while…</string> <string name="err_point_bear_and_dist_title">Need some help?</string> <string name="err_point_bear_and_dist">Fill both bearing and distance. Bearing is angle 0 to 360 degrees relative to north. Distance doesn\'t require units.</string> <string name="err_log_load_data">c:geo can\'t load data required to log visit.</string> <string name="err_log_load_data_again">c:geo can\'t load data required to log visit. Trying again.</string> <string name="err_log_load_data_still">c:geo is still loading data required to post log. Please wait a little while longer.</string> - <string name="err_log_post_failed">It seems that your log was not posted. Please check it on Geocaching.com.</string> - <string name="err_log_post_failed_ec">It seems that your log was not posted. Please check it on Extremcaching.com.</string> - <string name="err_logimage_post_failed">It seems that your log image was not uploaded. Please check it on Geocaching.com.</string> + <string name="err_log_post_failed">It seems that your log was not posted. Please check it on the cache originating website.</string> + <string name="err_logimage_post_failed">It seems that your log image was not uploaded. Please check it on the cache originating website.</string> <string name="err_search_address_forgot">c:geo forgot the address you tried to find.</string> <string name="err_parse_lat">c:geo can\'t parse latitude.</string> <string name="err_parse_lon">c:geo can\'t parse longitude.</string> @@ -228,6 +229,9 @@ <!-- location service --> <string name="loc_last">Last known</string> <string name="loc_net">Network</string> + <string name="loc_fused">Fused</string> + <string name="loc_low_power">Low-power</string> + <string name="loc_home">Home coordinates</string> <string name="loc_gps">GPS</string> <string name="loc_sat">Sat</string> <string name="loc_trying">Trying to Locate</string> @@ -251,7 +255,7 @@ <string name="caches_nearby_button">Nearby</string> <string name="advanced_search_button">Search</string> <string name="stored_caches_button">Stored</string> - <string name="any_button">Any destination</string> + <string name="any_button">Go to</string> <string name="unknown_scan">Didn\'t find any geocodes in the scan result.</string> <!-- caches --> @@ -295,9 +299,15 @@ <string name="caches_nearby">Nearby</string> <string name="caches_manage">Manage</string> <string name="caches_remove_all">Remove all</string> - <string name="caches_remove_all_confirm">Do you want to remove all %s caches from current list?</string> + <plurals name="caches_remove_all_confirm"> + <item quantity="one">Do you want to remove this cache from current list?</item> + <item quantity="other">Do you want to remove all %d caches from current list?</item> + </plurals> <string name="caches_remove_selected">Remove selected</string> - <string name="caches_remove_selected_confirm">Do you want to remove the selected %s caches from your device?</string> + <plurals name="caches_remove_selected_confirm"> + <item quantity="one">Do you want to remove this cache from your device?</item> + <item quantity="other">Do you want to remove the selected %d caches from your device?</item> + </plurals> <string name="caches_remove_progress">Removing caches</string> <string name="caches_delete_events">Delete past events</string> <string name="caches_refresh_selected">Refresh selected</string> @@ -317,13 +327,18 @@ <string name="caches_filter_track">With Trackables</string> <string name="caches_filter_clear">Clear filters</string> <string name="caches_filter_modified">With modified coordinates</string> + <string name="caches_filter_offline_log">With offline log</string> <string name="caches_filter_origin">Origin</string> <string name="caches_filter_distance">Distance</string> <string name="caches_filter_personal_note">With personal note</string> <string name="caches_filter_popularity">Favorites</string> <string name="caches_filter_popularity_ratio">Favorites [%]</string> + <string name="caches_filter_personal_data">With personal data</string> + <string name="caches_filter_rating">With rating</string> + <string name="caches_filter_own_rating">With own rating</string> <string name="caches_removing_from_history">Removing from History…</string> <string name="caches_clear_offlinelogs">Clear offline logs</string> + <string name="caches_clear_offlinelogs_message">Do you want to clear the offline logs?</string> <string name="caches_clear_offlinelogs_progress">Clearing offline logs</string> <!-- caches lists --> @@ -350,15 +365,19 @@ <!-- about --> <string name="about_version">Version</string> <string name="about_changelog">Changelog</string> + <string name="about_system">System</string> <string name="about_donate">Donate</string> <string name="about_donation_more">Donate\ndevelopment</string> <string name="about_contributors">Contributors</string> <string name="about_license">License</string> <string name="about_apache_license"><a href="">Apache License, Version 2.0</a></string> <string name="about_help">Help</string> + <string name="about_system_include">Please include the following system information when sending a bug report or asking for more information about c:geo:</string> + <string name="changelog_github">List of all changes</string> <!-- settings --> <string name="settings_title_services">Services</string> + <string name="settings_summary_services">Configure user account information and access to optional services.</string> <string name="settings_title_appearance">Appearance</string> <string name="settings_title_cachedetails">Cache Details</string> <string name="settings_title_offlinedata">Offline Data</string> @@ -409,6 +428,9 @@ <string name="settings_activate_oc_uk">Activate</string> <string name="init_oc_uk_description">Authorize c:geo with opencaching.org.uk to search for caches and access/filter your found caches.</string> <string name="init_gcvote">GCvote.com</string> + <string name="init_gcvote_password_description">To be able to rate a cache, you need to follow the instructions at GCVote.com and enter your GCVote password here.</string> + <string name="err_gcvote_send_rating">Error while sending rating, check GCVote password in settings or empty it.</string> + <string name="gcvote_sent">Voting successfully sent</string> <string name="init_twitter">Twitter</string> <string name="settings_activate_twitter">Activate</string> <string name="init_username">Username</string> @@ -479,6 +501,8 @@ <string name="init_backup_success">c:geo\'s database was successfully copied to:</string> <string name="init_backup_failed">Backup of c:geo\'s database failed.</string> <string name="init_backup_unnecessary">Database is empty, no backup necessary.</string> + <string name="backup_confirm_overwrite">Do you want to overwrite the existing backup from %s?</string> + <string name="restore_confirm_overwrite">Do you want to overwrite %s on your device with the backup?</string> <string name="init_restore_success">Restoration completed.</string> <string name="init_restore_failed">Restoration failed.</string> <string name="init_restore_running">Restoring cache database…</string> @@ -527,6 +551,12 @@ <string name="init_maintenance">Maintenance</string> <string name="init_maintenance_directories_note">c:geo stores images, log images and other files related to a cache in a separate directory. In some cases (like importing/exporting the database) this directory may contain outdated files, which can be deleted here.</string> <string name="init_maintenance_directories">Delete orphaned files</string> + <string name="init_location">Geolocation</string> + <string name="init_location_note">On devices equipped with Google Play Services, c:geo can automatically use a better geolocation provider. However, this prevents the use of an external BlueTooth GPS receiver.</string> + <string name="init_location_googleplayservices">Use Google Play Services</string> + <string name="init_low_power">Low-power mode</string> + <string name="init_low_power_note">The low-power mode avoids using the GPS and the gyroscope when a highly accurate location is not strictly necessary, at the cost of longer fixing times.</string> + <string name="init_low_power_mode">Activate low-power mode</string> <string name="init_create_memory_dump">Create memory dump</string> <string name="init_memory_dump">Memory dump</string> <string name="init_memory_dumped">Memory dumped to %s</string> @@ -648,6 +678,7 @@ <string name="cache_waypoints_add">Add Waypoint</string> <string name="cache_hint">Hint</string> + <string name="cache_hint_not_available">No hint available</string> <string name="cache_logs">Logbook</string> <string name="cache_logs_friends_and_own">Friends/Own Logs</string> <string name="cache_dialog_loading_details">Loading cache details…</string> @@ -687,9 +718,10 @@ <string name="cache_menu_streetview">Street View</string> <string name="cache_menu_browser">Open in browser</string> <string name="cache_menu_visit">Log Visit</string> - <string name="cache_menu_visit_offline">Log Visit offline</string> + <string name="cache_menu_visit_offline">One click offline log</string> <string name="cache_menu_spoilers">Spoiler images</string> <string name="cache_menu_around">Caches around</string> + <string name="around">Around %s</string> <string name="cache_menu_event">Add to calendar</string> <string name="cache_menu_details">Details</string> <string name="cache_menu_refresh">Refresh</string> @@ -699,6 +731,10 @@ <string name="cache_menu_oruxmaps">OruxMaps</string> <string name="cache_menu_navigon">Navigon</string> <string name="cache_menu_pebble">Pebble</string> + <string name="cache_menu_android_wear">Android Wear</string> + <string name="cache_menu_vote">Vote</string> + <string name="cache_menu_checker">Open Geochecker</string> + <string name="cache_menu_ignore">Ignore cache</string> <string name="cache_status">Status</string> <string name="cache_status_offline_log">Saved Log</string> <string name="cache_status_found">Found</string> @@ -825,7 +861,9 @@ <string name="search_clear_history">Clear History</string> <string name="search_history_cleared">History cleared</string> <string name="waypoint_coordinate_formats_plain">Plain</string> - + <string name="from_clipboard">From clipboard</string> + <string name="copy_to_clipboard">Copy to clipboard</string> + <!-- visit --> <string name="visit_tweet">Post this find to Twitter</string> @@ -938,11 +976,11 @@ <string name="license_dismiss">Dismiss</string> <!-- helpers --> - <string name="helper_calendar_title">c:geo calendar add-on</string> - <string name="helper_calendar_missing">c:geo calendar add-on not installed.</string> + <string name="helper_calendar_title">c:geo calendar plugin</string> + <string name="helper_calendar_missing">c:geo calendar plugin not installed.</string> <string name="helper_calendar_description">Enables you to export event caches to the calendar on your device.</string> <string name="helper_sendtocgeo_title">Send to c:geo</string> - <string name="helper_contacts_title">c:geo contacts add-on</string> + <string name="helper_contacts_title">c:geo contacts plugin</string> <string name="helper_contacts_description">Enables you to open a contact card (of your address book) directly from a log entry, so you can more easily ask friends for help.</string> <string name="helper_sendtocgeo_description">Send to c:geo is a browser extension <strong>for your PC</strong>. When browsing geocaching.com, you can send caches to your smartphone with the click of a button directly inside the browser.</string> <string name="helper_locus_title">Locus</string> @@ -959,7 +997,7 @@ <string name="helper_google_translate_description">If you download translation packages in the Google Translate app, then you can easily translate cache descriptions in c:geo by a long tap on the cache description text (without an Internet connection).</string> <!-- add-ons --> - <string name="addon_missing_title">Missing Add-On</string> + <string name="addon_missing_title">Missing plugin</string> <string name="addon_download_prompt">Get it now from Google Play.</string> <!-- export --> @@ -1207,13 +1245,15 @@ <string name="quote">To make geocaching easier, to make users lazier.</string> <string name="powered_by">carnero</string> <!-- Note: Links here are just for appearance. See AboutActivity to make changes --> - <string name="support">Support: <a href="">support@cgeo.org</a></string> - <string name="website">Website: <a href="">cgeo.org</a></string> - <string name="facebook">Facebook: <a href="">c:geo page</a></string> - <string name="twitter">Twitter: <a href="">@android_GC</a></string> - <string name="market">Android: <a href="">c:geo on Google Play</a></string> + <string name="support_title">Support</string> + <string name="website_title">Website</string> + <string name="facebook_title">Facebook</string> + <string name="facebook_link"><a href="">c:geo page</a></string> + <string name="twitter_title">Twitter</string> + <string name="market_title">Google Play</string> + <string name="market_link"><a href="">c:geo on Google Play</a></string> <string name="about_twitter">Should <b>c:geo</b> publish a new status on Twitter every time you log a cache?</string> - <string name="faq">FAQ: <a href="">faq.cgeo.org</a></string> + <string name="faq_title">FAQ</string> <!-- status (used via string based resource loading) --> <string name="status_new_release" tools:ignore="UnusedResources">New release available.\nClick to install.</string> @@ -1266,7 +1306,7 @@ <item quantity="other">%s favorites</item> </plurals> - <string name="percent_favorite_points">%\ favorites</string> + <string name="more_than_percent_favorite_points">> %d%% favorites</string> <!-- shortcuts --> <string name="cgeo_shortcut">c:geo shortcut</string> @@ -1279,4 +1319,8 @@ <string name="showcase_main_text">c:geo now places menu items in the title bar like other modern apps. Some items are hidden behind the dotted symbol. Long press a button to see its description.</string> <string name="showcase_cachelist_title">Switching lists</string> <string name="showcase_cachelist_text">You can switch between your geocache lists by clicking the title of the list.</string> + <string name="showcase_compass_hint_title">Show the hint</string> + <string name="showcase_compass_hint_text">This new menu item might give you an idea where to find the cache - it shows the hint, if available.</string> + <string name="confirm_log_title">Unusual log type</string> + <string name="confirm_log_message">You want to log \'%s\'. Are you sure?</string> </resources> diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml index 585500f..d216715 100644 --- a/main/res/values/strings_not_translatable.xml +++ b/main/res/values/strings_not_translatable.xml @@ -76,11 +76,14 @@ · <a href="http://code.google.com/p/mapsforge/">Mapsforge</a> (OSM-rendering)\n · <a href="http://thenounproject.com/">The Noun Project</a> (basis for attribute icons):\n    Â· USB by Kenneth Von Alt from The Noun Project\n +    Â· new-idea by Artem Korotkikh from The Noun Project\n · <a href="http://commons.apache.org/">The Apache Commons Project</a>\n · <a href="http://androidicons.com/">Android Icons</a> (<a href="https://creativecommons.org/licenses/by/3.0/">CC-BY 3.0</a>)\n · <a href="http://rrze-icon-set.berlios.de/index.html">RRZE Icon set</a> (<a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA 3.0</a>)\n · <a href="http://iconfindr.com/1mNr3rl">Layers icon by Cole Bemis</a> (<a href="http://creativecommons.org/licenses/by/3.0/">CC-BY 3.0</a>)\n · <a href="https://github.com/amlcurran/Showcaseview">ShowcaseView by Alex Curran</a> (<a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License 2.0</a>)\n + · <a href="http://www.mapquest.com/">Geocoding courtesy of MapQuest</a>\n + · <a href="http://www.openstreetmap.org/">Geocoding data from OpenStreetMap</a>\n </string> <!-- cache menu --> @@ -88,5 +91,10 @@ <string name="caches_map_mapswithme" translatable="false">Maps.me</string> <string name="cache_menu_mapswithme" translatable="false">Maps.me</string> + <string name="faq_link"><a href="">faq.cgeo.org</a></string> + <string name="website_link"><a href="">cgeo.org</a></string> + <string name="twitter_link"><a href="">@android_GC</a></string> + <string name="support_link"><a href="">support@cgeo.org</a></string> + </resources> diff --git a/main/res/values/styles.xml b/main/res/values/styles.xml index be1e1a4..5f280f2 100644 --- a/main/res/values/styles.xml +++ b/main/res/values/styles.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<resources> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> <!-- system definitions --> @@ -338,4 +338,13 @@ <item name="android:src">@drawable/mark_green</item> </style> + <style name="cacheRatingBar" parent="@android:style/Widget.RatingBar"> + <item name="android:progressDrawable">@drawable/star_rating</item> + <item name="android:minHeight">12dip</item> + <item name="android:maxHeight">22dip</item> + <item name="android:max">5</item> + <item name="android:stepSize">0.5</item> + <item name="android:isIndicator">true</item> + </style> + </resources>
\ No newline at end of file diff --git a/main/res/values/themes.xml b/main/res/values/themes.xml index 50485b3..751f325 100644 --- a/main/res/values/themes.xml +++ b/main/res/values/themes.xml @@ -9,7 +9,7 @@ <style name="cgeo_main.base" parent="@style/Theme.AppCompat"> - <!-- copy the style elements of the Wallpaper theme since AppCombat has no Wallpaper theme --> + <!-- copy the style elements of the Wallpaper theme since AppCompat has no Wallpaper theme --> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowShowWallpaper">true</item> diff --git a/main/res/xml/preferences.xml b/main/res/xml/preferences.xml index 1ed739d..48d8a21 100644 --- a/main/res/xml/preferences.xml +++ b/main/res/xml/preferences.xml @@ -6,7 +6,8 @@ <PreferenceScreen android:icon="?attr/settings_cloud" android:key="@string/preference_screen_services" - android:title="@string/settings_title_services" > + android:title="@string/settings_title_services" + android:summary="@string/settings_summary_services"> <PreferenceCategory android:title="@string/settings_category_geocaching" > <PreferenceScreen android:key="@string/preference_screen_gc" @@ -325,7 +326,13 @@ android:summary="@string/init_summary_ratingwanted" android:title="@string/init_ratingwanted" /> + <cgeo.geocaching.settings.TextPreference + android:dependency="@string/pref_ratingwanted" + android:layout="@layout/text_preference" + android:text="@string/init_gcvote_password_description" /> + <cgeo.geocaching.settings.EditPasswordPreference + android:dependency="@string/pref_ratingwanted" android:dialogTitle="@string/init_password" android:hint="@string/init_password" android:imeOptions="actionDone" @@ -430,7 +437,7 @@ android:title="@string/init_useenglish" /> <CheckBoxPreference android:defaultValue="false" - android:key="@string/pref_units" + android:key="@string/pref_units_imperial" android:summary="@string/init_summary_units" android:title="@string/init_units" /> </PreferenceScreen> @@ -697,6 +704,11 @@ <CheckBoxPreference android:defaultValue="true" android:enabled="false" + android:key="@string/pref_navigation_menu_android_wear" + android:title="@string/cache_menu_android_wear" /> + <CheckBoxPreference + android:defaultValue="true" + android:enabled="false" android:key="@string/pref_navigation_menu_mapswithme" android:title="@string/cache_menu_mapswithme" /> </PreferenceScreen> @@ -745,6 +757,25 @@ android:key="@string/pref_fakekey_preference_maintenance_directories" android:title="@string/init_maintenance_directories" /> </PreferenceCategory> + <PreferenceCategory android:title="@string/init_location"> + <cgeo.geocaching.settings.TextPreference + android:layout="@layout/text_preference" + android:text="@string/init_location_note" /> + + <CheckBoxPreference + android:defaultValue="true" + android:key="@string/pref_googleplayservices" + android:title="@string/init_location_googleplayservices" /> + </PreferenceCategory> + <PreferenceCategory android:title="@string/init_low_power"> + <cgeo.geocaching.settings.TextPreference + android:layout="@layout/text_preference" + android:text="@string/init_low_power_note" /> + <CheckBoxPreference + android:defaultValue="false" + android:key="@string/pref_lowpowermode" + android:title="@string/init_low_power_mode" /> + </PreferenceCategory> <PreferenceCategory android:title="@string/init_hardware_acceleration_title"> <cgeo.geocaching.settings.TextPreference android:layout="@layout/text_preference" diff --git a/main/src/cgeo/calendar/CalendarAddon.java b/main/src/cgeo/calendar/CalendarAddon.java index 4a672fa..88c67a8 100644 --- a/main/src/cgeo/calendar/CalendarAddon.java +++ b/main/src/cgeo/calendar/CalendarAddon.java @@ -2,12 +2,13 @@ package cgeo.calendar; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.location.GeopointFormatter; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.ProcessUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.content.DialogInterface; @@ -27,10 +28,11 @@ public class CalendarAddon { return ProcessUtils.isIntentAvailable(ICalendar.INTENT, Uri.parse(ICalendar.URI_SCHEME + "://" + ICalendar.URI_HOST)); } - public static void addToCalendarWithIntent(final Activity activity, final Geocache cache) { + public static void addToCalendarWithIntent(@NonNull final Activity activity, @NonNull final Geocache cache) { final Resources res = activity.getResources(); if (CalendarAddon.isAvailable()) { final Date hiddenDate = cache.getHiddenDate(); + final String startTime = cache.guessEventTimeMinutes() >= 0 ? String.valueOf(cache.guessEventTimeMinutes()) : StringUtils.EMPTY; final Parameters params = new Parameters( ICalendar.PARAM_NAME, cache.getName(), ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()), @@ -39,7 +41,7 @@ public class CalendarAddon { ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW), ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()), ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()), - ICalendar.PARAM_START_TIME_MINUTES, StringUtils.defaultString(cache.guessEventTimeMinutes()) + ICalendar.PARAM_START_TIME_MINUTES, startTime ); activity.startActivity(new Intent(ICalendar.INTENT, @@ -51,10 +53,8 @@ public class CalendarAddon { .append(res.getString(R.string.addon_download_prompt)) .toString(), new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int id) { - final Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(ICalendar.CALENDAR_ADDON_URI)); - activity.startActivity(intent); + public void onClick(final DialogInterface dialog, final int id) { + ProcessUtils.openMarket(activity, "cgeo.calendar"); } }); } diff --git a/main/src/cgeo/calendar/ICalendar.java b/main/src/cgeo/calendar/ICalendar.java index 6ecb6d5..9001198 100644 --- a/main/src/cgeo/calendar/ICalendar.java +++ b/main/src/cgeo/calendar/ICalendar.java @@ -1,19 +1,22 @@ package cgeo.calendar; +import org.eclipse.jdt.annotation.NonNull; + public interface ICalendar { - static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.calendar"; + @Deprecated + @NonNull static final String CALENDAR_ADDON_URI = "market://details?id=cgeo.calendar"; - static final String INTENT = "cgeo.calendar.RESERVE"; + @NonNull static final String INTENT = "cgeo.calendar.RESERVE"; - static final String URI_SCHEME = "add"; - static final String URI_HOST = "cgeo.org"; + @NonNull static final String URI_SCHEME = "add"; + @NonNull static final String URI_HOST = "cgeo.org"; - static final String PARAM_SHORT_DESC = "shortDesc"; // cache short description - static final String PARAM_HIDDEN_DATE = "hiddenDate"; // cache hidden date in milliseconds - static final String PARAM_URL = "url"; // cache URL - static final String PARAM_NOTE = "note"; // personal note - static final String PARAM_NAME = "name"; // cache name - static final String PARAM_LOCATION = "location"; // cache location, or empty string - static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string - static final String PARAM_START_TIME_MINUTES = "time"; // time of start + @NonNull static final String PARAM_SHORT_DESC = "shortDesc"; // cache short description + @NonNull static final String PARAM_HIDDEN_DATE = "hiddenDate"; // cache hidden date in milliseconds + @NonNull static final String PARAM_URL = "url"; // cache URL + @NonNull static final String PARAM_NOTE = "note"; // personal note + @NonNull static final String PARAM_NAME = "name"; // cache name + @NonNull static final String PARAM_LOCATION = "location"; // cache location, or empty string + @NonNull static final String PARAM_COORDS = "coords"; // cache coordinates, or empty string + @NonNull static final String PARAM_START_TIME_MINUTES = "time"; // time of start } diff --git a/main/src/cgeo/contacts/ContactsAddon.java b/main/src/cgeo/contacts/ContactsAddon.java index 7165a77..6c0dd21 100644 --- a/main/src/cgeo/contacts/ContactsAddon.java +++ b/main/src/cgeo/contacts/ContactsAddon.java @@ -3,6 +3,8 @@ package cgeo.contacts; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.ProcessUtils; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -13,7 +15,7 @@ public class ContactsAddon { // utility class } - public static void openContactCard(Activity context, String userName) { + public static void openContactCard(@NonNull final Activity context, @NonNull final String userName) { final Parameters params = new Parameters( IContacts.PARAM_NAME, userName ); diff --git a/main/src/cgeo/contacts/IContacts.java b/main/src/cgeo/contacts/IContacts.java index d68b78a..5a6c04d 100644 --- a/main/src/cgeo/contacts/IContacts.java +++ b/main/src/cgeo/contacts/IContacts.java @@ -1,10 +1,12 @@ package cgeo.contacts; +import org.eclipse.jdt.annotation.NonNull; + public interface IContacts { - static final String INTENT = "cgeo.contacts.FIND"; + @NonNull static final String INTENT = "cgeo.contacts.FIND"; - static final String URI_SCHEME = "find"; - static final String URI_HOST = "cgeo.org"; + @NonNull static final String URI_SCHEME = "find"; + @NonNull static final String URI_HOST = "cgeo.org"; - static final String PARAM_NAME = "name"; // user name + @NonNull static final String PARAM_NAME = "name"; // user name } diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index f6d204b..e5a98c2 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -3,9 +3,20 @@ package cgeo.geocaching; import butterknife.ButterKnife; import butterknife.InjectView; +import cgeo.calendar.CalendarAddon; +import cgeo.contacts.ContactsAddon; import cgeo.geocaching.activity.AbstractViewPagerActivity; +import cgeo.geocaching.compatibility.Compatibility; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.capability.ILogin; +import cgeo.geocaching.sensors.OrientationProvider; +import cgeo.geocaching.sensors.RotationProvider; +import cgeo.geocaching.sensors.Sensors; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; +import cgeo.geocaching.utils.ClipboardUtils; +import cgeo.geocaching.utils.ProcessUtils; import cgeo.geocaching.utils.Version; import org.apache.commons.io.IOUtils; @@ -17,15 +28,20 @@ import org.apache.commons.lang3.tuple.Pair; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; +import android.os.Build.VERSION; import android.os.Bundle; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.Button; import android.widget.ScrollView; import android.widget.TextView; import java.io.InputStream; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Scanner; public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> { @@ -65,6 +81,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> @InjectView(R.id.changelog_master) protected TextView changeLogMaster; @InjectView(R.id.changelog_release) protected TextView changeLogRelease; + @InjectView(R.id.changelog_github) protected TextView changeLogLink; @Override public ScrollView getDispatchedView(final ViewGroup parentView) { @@ -77,11 +94,42 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> } else { changeLogMaster.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); } + changeLogLink.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(final View v) { + startUrl("https://github.com/cgeo/cgeo/releases"); + } + }); return view; } } + class SystemViewCreator extends AbstractCachingPageViewCreator<ScrollView> { + + @InjectView(R.id.system) protected TextView system; + @InjectView(R.id.copy) protected Button copy; + + @Override + public ScrollView getDispatchedView(final ViewGroup parentView) { + final ScrollView view = (ScrollView) getLayoutInflater().inflate(R.layout.about_system_page, parentView, false); + ButterKnife.inject(this, view); + final String systemInfo = systemInformation(AboutActivity.this); + system.setText(systemInfo); + system.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + Compatibility.setTextIsSelectable(system, true); + copy.setOnClickListener(new OnClickListener() { + @Override + public void onClick(final View view) { + ClipboardUtils.copyToClipboard(systemInfo); + showShortToast(getString(R.string.clipboard_copy_ok)); + } + }); + return view; + } + } + class HelpViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @InjectView(R.id.support) protected TextView support; @@ -95,7 +143,8 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> public ScrollView getDispatchedView(final ViewGroup parentView) { final ScrollView view = (ScrollView) getLayoutInflater().inflate(R.layout.about_help_page, parentView, false); ButterKnife.inject(this, view); - setClickListener(support, "mailto:support@cgeo.org?subject=" + Uri.encode("cgeo " + Version.getVersionName(AboutActivity.this))); + setClickListener(support, "mailto:support@cgeo.org?subject=" + Uri.encode("cgeo " + Version.getVersionName(AboutActivity.this)) + + "&body=" + Uri.encode(systemInformation(AboutActivity.this)) + "\n"); setClickListener(website, "http://www.cgeo.org/"); setClickListener(facebook, "http://www.facebook.com/pages/cgeo/297269860090"); setClickListener(twitter, "http://twitter.com/android_gc"); @@ -104,7 +153,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> @Override public void onClick(final View v) { - market(); + ProcessUtils.openMarket(AboutActivity.this, getPackageName()); } }); return view; @@ -131,6 +180,7 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> VERSION(R.string.about_version), HELP(R.string.about_help), CHANGELOG(R.string.about_changelog), + SYSTEM(R.string.about_system), CONTRIBUTORS(R.string.about_contributors), LICENSE(R.string.about_license); @@ -168,12 +218,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } - final void market() { - final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())); - marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - startActivity(marketIntent); - } - @Override protected final cgeo.geocaching.activity.AbstractViewPagerActivity.PageViewCreator createViewCreator(final Page page) { switch (page) { @@ -183,6 +227,8 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> return new HelpViewCreator(); case CHANGELOG: return new ChangeLogViewCreator(); + case SYSTEM: + return new SystemViewCreator(); case CONTRIBUTORS: return new ContributorsViewCreator(); case LICENSE: @@ -224,4 +270,57 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> fromActivity.startActivity(intent); } + private static String presence(final Boolean present) { + return present ? "present" : "absent"; + } + + private static String systemInformation(final Context context) { + final boolean googlePlayServicesAvailable = CgeoApplication.getInstance().isGooglePlayServicesAvailable(); + final StringBuilder body = new StringBuilder("--- System information ---") + .append("\nDevice: ").append(Build.MODEL).append(" (").append(Build.PRODUCT).append(", ").append(Build.BRAND).append(")") + .append("\nAndroid version: ").append(VERSION.RELEASE) + .append("\nAndroid build: ").append(Build.DISPLAY) + .append("\nCgeo version: ").append(Version.getVersionName(context)) + .append("\nGoogle Play services: ").append(googlePlayServicesAvailable ? (Settings.useGooglePlayServices() ? "enabled" : "disabled") : "unavailable") + .append("\nLow power mode: ").append(Settings.useLowPowerMode() ? "active" : "inactive") + .append("\nCompass capabilities: ").append(Sensors.getInstance().hasCompassCapabilities() ? "yes" : "no") + .append("\nRotation sensor: ").append(presence(RotationProvider.hasRotationSensor(context))) + .append("\nGeomagnetic rotation sensor: ").append(presence(RotationProvider.hasGeomagneticRotationSensor(context))) + .append("\nOrientation sensor: ").append(presence(OrientationProvider.hasOrientationSensor(context))) + .append("\nHide own/found: ").append(Settings.isExcludeMyCaches()) + .append("\nMap strategy: ").append(Settings.getLiveMapStrategy().toString().toLowerCase(Locale.getDefault())) + .append("\nHW-acceleration: ").append(Settings.useHardwareAcceleration() ? "enabled" : "disabled") + .append(" (").append(Settings.useHardwareAcceleration() != Settings.HW_ACCEL_DISABLED_BY_DEFAULT ? "default state" : "manually changed").append(")"); + final StringBuilder connectors = new StringBuilder(); + int connectorCount = 0; + for (final ILogin connector : ConnectorFactory.getActiveLiveConnectors()) { + connectorCount++; + connectors.append("\n - ").append(connector.getName()).append(": ").append(connector.isLoggedIn() ? "logged in" : "not logged in") + .append(" (").append(connector.getLoginStatusString()).append(')'); + if (connector.getName().equals("geocaching.com") && connector.isLoggedIn()) { + connectors.append(" / ").append(Settings.getGCMemberStatus()); + } + } + body.append("\nGeocaching sites enabled:").append(connectorCount > 0 ? connectors : " none") + .append("\nSystem language: ").append(Locale.getDefault()); + if (Settings.isUseEnglish()) { + body.append(" (cgeo forced to English)"); + } + final boolean calendarAddonAvailable = CalendarAddon.isAvailable(); + final boolean contactsAddonAvailable = ContactsAddon.isAvailable(); + body.append("\nInstalled cgeo plugins:"); + if (calendarAddonAvailable || contactsAddonAvailable) { + if (calendarAddonAvailable) { + body.append(" calendar"); + } + if (contactsAddonAvailable) { + body.append(" contacts"); + } + } else { + body.append(" none"); + } + body.append("\n--- End of system information ---\n"); + return body.toString(); + } + } diff --git a/main/src/cgeo/geocaching/AbstractDialogFragment.java b/main/src/cgeo/geocaching/AbstractDialogFragment.java index 9277d8c..6e58bd3 100644 --- a/main/src/cgeo/geocaching/AbstractDialogFragment.java +++ b/main/src/cgeo/geocaching/AbstractDialogFragment.java @@ -7,10 +7,10 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.gcvote.GCVote; import cgeo.geocaching.gcvote.GCVoteRating; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.LoggingUI; @@ -19,7 +19,7 @@ import cgeo.geocaching.utils.RxUtils; import rx.Observable; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; import rx.subscriptions.Subscriptions; @@ -41,7 +41,6 @@ import android.widget.ImageView; import android.widget.TextView; public abstract class AbstractDialogFragment extends DialogFragment implements CacheMenuHandler.ActivityInterface, PopupMenu.OnMenuItemClickListener, MenuItem.OnMenuItemClickListener { - protected CgeoApplication app = null; protected Resources res = null; protected String geocode; protected CacheDetailsCreator details; @@ -60,7 +59,6 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); res = getResources(); - app = (CgeoApplication) getActivity().getApplication(); setHasOptionsMenu(true); } @@ -189,7 +187,7 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C if (!cache.supportsGCVote()) { return; } - AndroidObservable.bindActivity(getActivity(), Observable.defer(new Func0<Observable<GCVoteRating>>() { + AppObservable.bindActivity(getActivity(), Observable.defer(new Func0<Observable<GCVoteRating>>() { @Override public Observable<GCVoteRating> call() { final GCVoteRating rating = GCVote.getRating(cache.getGuid(), geocode); @@ -256,15 +254,15 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C private final GeoDirHandler geoUpdate = new GeoDirHandler() { @Override - public void updateGeoData(final IGeoData geo) { + public void updateGeoData(final GeoData geo) { try { - if (geo.getCoords() != null && cache != null && cache.getCoords() != null) { + if (cache != null && cache.getCoords() != null) { cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords()))); cacheDistance.bringToFront(); } onUpdateGeoData(geo); } catch (final RuntimeException e) { - Log.w("Failed to UpdateLocation location."); + Log.w("Failed to update location", e); } } }; @@ -273,7 +271,7 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C * @param geo * location */ - protected void onUpdateGeoData(final IGeoData geo) { + protected void onUpdateGeoData(final GeoData geo) { // do nothing by default } @@ -324,7 +322,7 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C try { CacheMenuHandler.onPrepareOptionsMenu(menu, cache); LoggingUI.onPrepareOptionsMenu(menu, cache); - } catch (final RuntimeException e) { + } catch (final RuntimeException ignored) { // nothing } } @@ -342,7 +340,7 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C showToast(res.getString(R.string.err_location_unknown)); return; } - CacheListActivity.startActivityCoordinates((AbstractActivity) getActivity(), coords); + CacheListActivity.startActivityCoordinates((AbstractActivity) getActivity(), coords, cache != null ? cache.getName() : null); getActivity().finish(); } diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java index 8448e45..cc5546f 100644 --- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java +++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.activity.Keyboard; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCSmiliesProvider; @@ -11,6 +12,8 @@ import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; +import org.apache.commons.lang3.StringUtils; + import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; @@ -55,6 +58,10 @@ public abstract class AbstractLoggingActivity extends AbstractActionBarActivity @Override public boolean onOptionsItemSelected(final MenuItem item) { final int id = item.getItemId(); + if (id == R.id.menu_repeat_last) { + replaceLog(getLastLog()); + return true; + } final LogTemplate template = LogTemplateProvider.getTemplate(id); if (template != null) { @@ -71,10 +78,26 @@ public abstract class AbstractLoggingActivity extends AbstractActionBarActivity return super.onOptionsItemSelected(item); } + /** + * @return the last log text used with this logging activity + */ + protected abstract String getLastLog(); + protected abstract LogContext getLogContext(); protected final void insertIntoLog(final String newText, final boolean moveCursor) { final EditText log = (EditText) findViewById(R.id.log); ActivityMixin.insertAtPosition(log, newText, moveCursor); } + + private void replaceLog(final String newText) { + final EditText log = (EditText) findViewById(R.id.log); + log.setText(StringUtils.EMPTY); + insertIntoLog(newText, true); + } + + protected void requestKeyboardForLogging() { + new Keyboard(this).show(findViewById(R.id.log)); + } + } diff --git a/main/src/cgeo/geocaching/AddressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java index dc0239f..4ff48f6 100644 --- a/main/src/cgeo/geocaching/AddressListActivity.java +++ b/main/src/cgeo/geocaching/AddressListActivity.java @@ -1,75 +1,55 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractListActivity; +import cgeo.geocaching.location.AndroidGeocoder; +import cgeo.geocaching.location.GCGeocoder; +import cgeo.geocaching.location.MapQuestGeocoder; import cgeo.geocaching.ui.AddressListAdapter; -import cgeo.geocaching.utils.Log; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; +import rx.Observable; +import rx.android.app.AppObservable; +import rx.functions.Action1; import android.app.ProgressDialog; import android.location.Address; -import android.location.Geocoder; -import android.os.AsyncTask; import android.os.Bundle; import java.util.List; -import java.util.Locale; public class AddressListActivity extends AbstractListActivity { @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.addresslist_activity); - // get parameters - final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD); - - if (keyword == null) { - showToast(res.getString(R.string.err_search_address_forgot)); - finish(); - return; - } - final AddressListAdapter adapter = new AddressListAdapter(this); setListAdapter(adapter); + final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD); final ProgressDialog waitDialog = ProgressDialog.show(this, res.getString(R.string.search_address_started), keyword, true); waitDialog.setCancelable(true); + lookupAddressInBackground(keyword, adapter, waitDialog); + } - new AsyncTask<Void, Void, List<Address>>() { - + private void lookupAddressInBackground(final String keyword, final AddressListAdapter adapter, final ProgressDialog waitDialog) { + final Observable<Address> geocoderObservable = new AndroidGeocoder(this).getFromLocationName(keyword) + .onErrorResumeNext(MapQuestGeocoder.getFromLocationName(keyword)) + .onErrorResumeNext(GCGeocoder.getFromLocationName(keyword)); + AppObservable.bindActivity(this, geocoderObservable.toList()).subscribe(new Action1<List<Address>>() { @Override - protected List<Address> doInBackground(Void... params) { - final Geocoder geocoder = new Geocoder(AddressListActivity.this, Locale.getDefault()); - try { - return geocoder.getFromLocationName(keyword, 20); - } catch (Exception e) { - // non Google devices come without the geocoder - if (StringUtils.containsIgnoreCase(e.getMessage(), "Service not Available")) { - Log.i("No geocoder available"); - } - else { - Log.e("AddressListActivity.doInBackground", e); - } - return null; + public void call(final List<Address> addresses) { + waitDialog.dismiss(); + for (final Address address : addresses) { + adapter.add(address); // don't use addAll, it's only available with API >= 11 } } - + }, new Action1<Throwable>() { @Override - protected void onPostExecute(final List<Address> addresses) { - waitDialog.dismiss(); - if (CollectionUtils.isNotEmpty(addresses)) { - for (final Address address : addresses) { - adapter.add(address); // don't use addAll, it's only available with API >= 11 - } - } else { - finish(); - CacheListActivity.startActivityAddress(AddressListActivity.this, null, keyword); - } + public void call(final Throwable throwable) { + finish(); + showToast(res.getString(R.string.err_unknown_address)); } - - }.execute(); + }); } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/AttributesGridAdapter.java b/main/src/cgeo/geocaching/AttributesGridAdapter.java new file mode 100644 index 0000000..fd81339 --- /dev/null +++ b/main/src/cgeo/geocaching/AttributesGridAdapter.java @@ -0,0 +1,79 @@ +package cgeo.geocaching; + +import cgeo.geocaching.enumerations.CacheAttribute; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import java.util.List; + +public class AttributesGridAdapter extends BaseAdapter { + private final Context context; + private final Resources resources; + private final List<String> attributes; + private final LayoutInflater inflater; + + public AttributesGridAdapter(final Context context, final Geocache cache) { + this.context = context; + resources = context.getResources(); + attributes = cache.getAttributes(); + inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @Override + public int getCount() { + return attributes.size(); + } + + @Override + public Object getItem(final int position) { + return attributes.get(position); + } + + @Override + public long getItemId(final int position) { + return 0; + } + + @Override + public View getView(final int position, final View convertView, final ViewGroup parent) { + final FrameLayout attributeLayout; + if (convertView == null) { + attributeLayout = (FrameLayout) inflater.inflate(R.layout.attribute_image, parent, false); + } else { + attributeLayout = (FrameLayout) convertView; + } + + drawAttribute(attributeLayout, attributes.get(position)); + return attributeLayout; + } + + private void drawAttribute(final FrameLayout attributeLayout, final String attributeName) { + final ImageView imageView = (ImageView) attributeLayout.getChildAt(0); + + final boolean strikeThrough = !CacheAttribute.isEnabled(attributeName); + final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName)); + if (attrib != null) { + Drawable drawable = resources.getDrawable(attrib.drawableId); + imageView.setImageDrawable(drawable); + if (strikeThrough) { + // generate strike through image with same properties as attribute image + final ImageView strikeThroughImage = new ImageView(context); + strikeThroughImage.setLayoutParams(imageView.getLayoutParams()); + drawable = resources.getDrawable(R.drawable.attribute__strikethru); + strikeThroughImage.setImageDrawable(drawable); + attributeLayout.addView(strikeThroughImage); + } + } else { + imageView.setImageDrawable(resources.getDrawable(R.drawable.attribute_unknown)); + } + } + +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/CacheCache.java b/main/src/cgeo/geocaching/CacheCache.java index 1913d3c..74e22b5 100644 --- a/main/src/cgeo/geocaching/CacheCache.java +++ b/main/src/cgeo/geocaching/CacheCache.java @@ -3,7 +3,7 @@ package cgeo.geocaching; import cgeo.geocaching.DataStore.StorageLocation; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.LeastRecentlyUsedMap.RemoveHandler; import cgeo.geocaching.utils.Log; diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 0976b35..4f0c4d2 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -5,29 +5,31 @@ import butterknife.InjectView; import cgeo.calendar.CalendarAddon; import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.activity.AbstractActivity.ActivitySharingInterface; import cgeo.geocaching.activity.AbstractViewPagerActivity; import cgeo.geocaching.activity.INavigationSource; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider; import cgeo.geocaching.apps.cachelist.MapsWithMeCacheListApp; -import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.capability.IgnoreCapability; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.enumerations.CacheAttribute; -import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.gcvote.GCVote; +import cgeo.geocaching.gcvote.GCVoteDialog; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.network.AndroidBeam; import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.SmileyImage; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; @@ -44,7 +46,7 @@ import cgeo.geocaching.ui.OwnerActionsClickListener; import cgeo.geocaching.ui.WeakReferenceHandler; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.ui.logs.CacheLogsViewCreator; -import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.CheckerUtils; import cgeo.geocaching.utils.CryptUtils; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.ImageUtils; @@ -66,10 +68,12 @@ import org.eclipse.jdt.annotation.Nullable; import rx.Observable; import rx.Observable.OnSubscribe; import rx.Subscriber; -import rx.android.observables.AndroidObservable; +import rx.Subscription; +import rx.android.app.AppObservable; import rx.functions.Action0; import rx.functions.Action1; import rx.subscriptions.CompositeSubscription; +import rx.subscriptions.Subscriptions; import android.R.color; import android.app.AlertDialog; @@ -84,6 +88,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -97,6 +102,7 @@ import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; +import android.text.util.Linkify; import android.util.TypedValue; import android.view.ContextMenu; import android.view.Menu; @@ -105,16 +111,15 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.view.ViewParent; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; -import android.widget.FrameLayout; +import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; import android.widget.TextView.BufferType; @@ -133,7 +138,7 @@ import java.util.regex.Pattern; * e.g. details, description, logs, waypoints, inventory... */ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> - implements CacheMenuHandler.ActivityInterface, INavigationSource, ActivitySharingInterface, EditNoteDialogListener { + implements CacheMenuHandler.ActivityInterface, INavigationSource, AndroidBeam.ActivitySharingInterface, EditNoteDialogListener { private static final int MESSAGE_FAILED = -1; private static final int MESSAGE_SUCCEEDED = 1; @@ -171,6 +176,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc */ private Waypoint selectedWaypoint; + private boolean requireGeodata; + private Subscription geoDataSubscription = Subscriptions.empty(); + @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.cachedetail_activity); @@ -179,12 +187,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // get parameters final Bundle extras = getIntent().getExtras(); - final Uri uri = getIntent().getData(); + final Uri uri = AndroidBeam.getUri(getIntent()); // try to get data from extras String name = null; String geocode = null; String guid = null; + if (extras != null) { geocode = extras.getString(Intents.EXTRA_GEOCODE); name = extras.getString(Intents.EXTRA_NAME); @@ -196,6 +205,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc geocode = MapsWithMeCacheListApp.getCacheFromMapsWithMe(this, getIntent()); } + if (geocode == null && uri != null) { + geocode = ConnectorFactory.getGeocodeFromURL(uri.toString()); + } + // try to get data from URI if (geocode == null && guid == null && uri != null) { final String uriHost = uri.getHost().toLowerCase(Locale.US); @@ -227,31 +240,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return; } } - } else if (uriHost.contains("coord.info")) { - if (StringUtils.startsWith(uriPath, "/gc")) { - geocode = uriPath.substring(1).toUpperCase(Locale.US); - } else { - showToast(res.getString(R.string.err_detail_open)); - finish(); - return; - } - } else if (uriHost.contains("opencaching.de")) { - if (StringUtils.startsWith(uriPath, "/oc")) { - geocode = uriPath.substring(1).toUpperCase(Locale.US); - } else { - geocode = uri.getQueryParameter("wp"); - if (StringUtils.isNotBlank(geocode)) { - geocode = geocode.toUpperCase(Locale.US); - } else { - showToast(res.getString(R.string.err_detail_open)); - finish(); - return; - } - } - } else { - showToast(res.getString(R.string.err_detail_open)); - finish(); - return; } } @@ -263,7 +251,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } // If we open this cache from a search, let's properly initialize the title bar, even if we don't have cache details - updateTitleBar(geocode, name, null); + setCacheTitleBar(geocode, name, null); final LoadCacheHandler loadCacheHandler = new LoadCacheHandler(this, progress); @@ -275,7 +263,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc title = geocode; } progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, loadCacheHandler.cancelMessage()); - } catch (final RuntimeException e) { + } catch (final RuntimeException ignored) { // nothing, we lost the window } @@ -293,8 +281,16 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (getPage(position) == Page.IMAGES) { loadCacheImages(); } + requireGeodata = getPage(position) == Page.DETAILS; + startOrStopGeoDataListener(); + + // cancel contextual actions on page change + if (currentActionMode != null) { + currentActionMode.finish(); + } } }); + requireGeodata = pageToOpen == 1; final String realGeocode = geocode; final String realGuid = guid; @@ -309,10 +305,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc locationUpdater = new CacheDetailsGeoDirHandler(this); // If we have a newer Android device setup Android Beam for easy cache sharing - initializeAndroidBeam(this); + AndroidBeam.enable(this, this); } @Override + @Nullable public String getAndroidBeamUri() { return cache != null ? cache.getCgeoUrl() : null; } @@ -323,9 +320,17 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc outState.putInt(STATE_PAGE_INDEX, getCurrentItem()); } + private void startOrStopGeoDataListener() { + geoDataSubscription.unsubscribe(); + if (requireGeodata) { + geoDataSubscription = locationUpdater.start(GeoDirHandler.UPDATE_GEODATA); + } + } + @Override public void onResume() { - super.onResume(locationUpdater.start(GeoDirHandler.UPDATE_GEODATA)); + super.onResume(); + startOrStopGeoDataListener(); if (refreshOnResume) { notifyDataSetChanged(); @@ -334,6 +339,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } @Override + public void onPause() { + geoDataSubscription.unsubscribe(); + super.onPause(); + } + + @Override public void onDestroy() { createSubscriptions.unsubscribe(); super.onDestroy(); @@ -389,17 +400,43 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return true; case R.id.menu_waypoint_duplicate: ensureSaved(); - if (cache.duplicateWaypoint(selectedWaypoint)) { - DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); - notifyDataSetChanged(); - } + new AsyncTask<Void, Void, Boolean>() { + @Override + protected Boolean doInBackground(final Void... params) { + if (cache.duplicateWaypoint(selectedWaypoint)) { + DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); + return true; + } + return false; + } + + @Override + protected void onPostExecute(final Boolean result) { + if (result) { + notifyDataSetChanged(); + } + } + }.execute(); return true; case R.id.menu_waypoint_delete: ensureSaved(); - if (cache.deleteWaypoint(selectedWaypoint)) { - DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); - notifyDataSetChanged(); - } + new AsyncTask<Void, Void, Boolean>() { + @Override + protected Boolean doInBackground(final Void... params) { + if (cache.deleteWaypoint(selectedWaypoint)) { + DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); + return true; + } + return false; + } + + @Override + protected void onPostExecute(final Boolean result) { + if (result) { + notifyDataSetChanged(); + } + } + }.execute(); return true; case R.id.menu_waypoint_navigate_default: if (selectedWaypoint != null) { @@ -413,17 +450,17 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return true; case R.id.menu_waypoint_caches_around: if (selectedWaypoint != null) { - CacheListActivity.startActivityCoordinates(this, selectedWaypoint.getCoords()); + CacheListActivity.startActivityCoordinates(this, selectedWaypoint.getCoords(), selectedWaypoint.getName()); } return true; case R.id.menu_waypoint_reset_cache_coords: ensureSaved(); if (ConnectorFactory.getConnector(cache).supportsOwnCoordinates()) { - createResetCacheCoordinatesDialog(cache, selectedWaypoint).show(); + createResetCacheCoordinatesDialog(selectedWaypoint).show(); } else { final ProgressDialog progressDialog = ProgressDialog.show(this, getString(R.string.cache), getString(R.string.waypoint_reset), true); final HandlerResetCoordinates handler = new HandlerResetCoordinates(this, progressDialog, false); - new ResetCoordsThread(cache, handler, selectedWaypoint, true, false, progressDialog).start(); + resetCoords(cache, handler, selectedWaypoint, true, false, progressDialog); } return true; case R.id.menu_calendar: @@ -441,13 +478,12 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onCreateOptionsMenu(final Menu menu) { CacheMenuHandler.addMenuItems(this, menu, cache); - MenuItem menuItem = menu.findItem(R.id.menu_default_navigation); + final MenuItem menuItem = menu.findItem(R.id.menu_default_navigation); final NavigationActionProvider navAction = (NavigationActionProvider) MenuItemCompat.getActionProvider(menuItem); if (navAction != null) { navAction.setNavigationSource(this); } - menuItem = menu.findItem(R.id.menu_navigate); - NavigationSelectionActionProvider.initialize(menuItem, cache); + NavigationSelectionActionProvider.initialize(menu.findItem(R.id.menu_navigate), cache); return true; } @@ -458,6 +494,18 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc menu.findItem(R.id.menu_store).setVisible(cache != null && !cache.isOffline()); menu.findItem(R.id.menu_delete).setVisible(cache != null && cache.isOffline()); menu.findItem(R.id.menu_refresh).setVisible(cache != null && cache.isOffline()); + menu.findItem(R.id.menu_gcvote).setVisible(cache != null && GCVote.isVotingPossible(cache)); + menu.findItem(R.id.menu_checker).setVisible(cache != null && StringUtils.isNotEmpty(CheckerUtils.getCheckerUrl(cache))); + // Comment out ignoring capabilities for this release, as this feature needs to be polished and accessible from + // other places as well as undo-able. + /* + if (cache != null) { + final IConnector connector = ConnectorFactory.getConnector(cache); + if (connector instanceof IgnoreCapability) { + menu.findItem(R.id.menu_ignore).setVisible(((IgnoreCapability) connector).canIgnoreCache(cache)); + } + } + */ return super.onPrepareOptionsMenu(menu); } @@ -479,6 +527,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc case R.id.menu_refresh: refreshCache(); return true; + case R.id.menu_gcvote: + showVoteDialog(); + return true; + case R.id.menu_checker: + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(CheckerUtils.getCheckerUrl(cache)))); + return true; + case R.id.menu_ignore: + ignoreCache(); + return true; default: if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) { return true; @@ -492,6 +549,24 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return super.onOptionsItemSelected(item); } + private void ignoreCache() { + RxUtils.networkScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + ((IgnoreCapability) ConnectorFactory.getConnector(cache)).ignoreCache(cache); + } + }); + } + + private void showVoteDialog() { + GCVoteDialog.show(this, cache, new Runnable() { + @Override + public void run() { + notifyDataSetChanged(); + } + }); + } + private static final class CacheDetailsGeoDirHandler extends GeoDirHandler { private final WeakReference<CacheDetailActivity> activityRef; @@ -500,7 +575,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } @Override - public void updateGeoData(final IGeoData geo) { + public void updateGeoData(final GeoData geo) { final CacheDetailActivity activity = activityRef.get(); if (activity == null) { return; @@ -509,7 +584,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return; } - if (geo.getCoords() != null && activity.cache != null && activity.cache.getCoords() != null) { + if (activity.cache != null && activity.cache.getCoords() != null) { activity.cacheDistanceView.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(activity.cache.getCoords()))); activity.cacheDistanceView.bringToFront(); } @@ -570,7 +645,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } private void notifyDataSetChanged() { - // This might get called asynchronically when the activity is shut down + // This might get called asynchronous when the activity is shut down if (isFinishing()) { return; } @@ -591,7 +666,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // allow cache to notify CacheDetailActivity when it changes so it can be reloaded cache.setChangeNotificationHandler(new ChangeNotificationHandler(this, progress)); - updateTitleBar(cache.getGeocode(), cache.getName(), cache.getType()); + setCacheTitleBar(cache); // reset imagesList so Images view page will be redrawn imagesList = null; @@ -604,19 +679,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc Settings.addCacheToHistory(cache.getGeocode()); } - private void updateTitleBar(@Nullable final String geocode, @Nullable final String name, @Nullable final CacheType type) { - if (StringUtils.isNotBlank(name)) { - setTitle(StringUtils.isNotBlank(geocode) ? name + " (" + geocode + ")" : name); - } else { - setTitle(StringUtils.isNotBlank(geocode) ? geocode : res.getString(R.string.cache)); - } - if (type != null) { - getSupportActionBar().setIcon(getResources().getDrawable(type.markerId)); - } else { - getSupportActionBar().setIcon(android.R.color.transparent); - } - } - /** * Tries to navigate to the {@link Geocache} of this activity using the default navigation tool. */ @@ -688,193 +750,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } } - private class AttributeViewBuilder { - private ViewGroup attributeIconsLayout; // layout for attribute icons - private ViewGroup attributeDescriptionsLayout; // layout for attribute descriptions - private boolean attributesShowAsIcons = true; // default: show icons - /** - * If the cache is from a non GC source, it might be without icons. Disable switching in those cases. - */ - private boolean noAttributeIconsFound = false; - private int attributeBoxMaxWidth; - - public void fillView(final LinearLayout attributeBox) { - // first ensure that the view is empty - attributeBox.removeAllViews(); - - // maximum width for attribute icons is screen width - paddings of parents - attributeBoxMaxWidth = Compatibility.getDisplayWidth(); - ViewParent child = attributeBox; - do { - if (child instanceof View) { - attributeBoxMaxWidth -= ((View) child).getPaddingLeft() + ((View) child).getPaddingRight(); - } - child = child.getParent(); - } while (child != null); - - // delete views holding description / icons - attributeDescriptionsLayout = null; - attributeIconsLayout = null; - - attributeBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(final View v) { - // toggle between attribute icons and descriptions - toggleAttributeDisplay(attributeBox, attributeBoxMaxWidth); - } - }); - - // icons or text? - // - // also show icons when noAttributeImagesFound == true. Explanation: - // 1. no icons could be found in the first invocation of this method - // 2. user refreshes cache from web - // 3. now this method is called again - // 4. attributeShowAsIcons is false but noAttributeImagesFound is true - // => try to show them now - if (attributesShowAsIcons || noAttributeIconsFound) { - showAttributeIcons(attributeBox, attributeBoxMaxWidth); - } else { - showAttributeDescriptions(attributeBox); - } - } - - /** - * lazy-creates the layout holding the icons of the caches attributes - * and makes it visible - */ - private void showAttributeIcons(final LinearLayout attribBox, final int parentWidth) { - if (attributeIconsLayout == null) { - attributeIconsLayout = createAttributeIconsLayout(parentWidth); - // no matching icons found? show text - if (noAttributeIconsFound) { - showAttributeDescriptions(attribBox); - return; - } - } - attribBox.removeAllViews(); - attribBox.addView(attributeIconsLayout); - attributesShowAsIcons = true; - } - - /** - * lazy-creates the layout holding the descriptions of the caches attributes - * and makes it visible - */ - private void showAttributeDescriptions(final LinearLayout attribBox) { - if (attributeDescriptionsLayout == null) { - attributeDescriptionsLayout = createAttributeDescriptionsLayout(attribBox); - } - attribBox.removeAllViews(); - attribBox.addView(attributeDescriptionsLayout); - attributesShowAsIcons = false; - } - - /** - * toggle attribute descriptions and icons - */ - private void toggleAttributeDisplay(final LinearLayout attribBox, final int parentWidth) { - // Don't toggle when there are no icons to show. - if (noAttributeIconsFound) { - return; - } - - // toggle - if (attributesShowAsIcons) { - showAttributeDescriptions(attribBox); - } else { - showAttributeIcons(attribBox, parentWidth); - } - } - - private ViewGroup createAttributeIconsLayout(final int parentWidth) { - final LinearLayout rows = new LinearLayout(CacheDetailActivity.this); - rows.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); - rows.setOrientation(LinearLayout.VERTICAL); - - LinearLayout attributeRow = newAttributeIconsRow(); - rows.addView(attributeRow); - - noAttributeIconsFound = true; - - for (final String attributeName : cache.getAttributes()) { - // check if another attribute icon fits in this row - attributeRow.measure(0, 0); - final int rowWidth = attributeRow.getMeasuredWidth(); - final FrameLayout fl = (FrameLayout) getLayoutInflater().inflate(R.layout.attribute_image, attributeRow, false); - final ImageView iv = (ImageView) fl.getChildAt(0); - if ((parentWidth - rowWidth) < iv.getLayoutParams().width) { - // make a new row - attributeRow = newAttributeIconsRow(); - rows.addView(attributeRow); - } - - final boolean strikeThrough = !CacheAttribute.isEnabled(attributeName); - final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName)); - if (attrib != null) { - noAttributeIconsFound = false; - Drawable d = res.getDrawable(attrib.drawableId); - iv.setImageDrawable(d); - // strike through? - if (strikeThrough) { - // generate strike through image with same properties as attribute image - final ImageView strikeThroughImage = new ImageView(CacheDetailActivity.this); - strikeThroughImage.setLayoutParams(iv.getLayoutParams()); - d = res.getDrawable(R.drawable.attribute__strikethru); - strikeThroughImage.setImageDrawable(d); - fl.addView(strikeThroughImage); - } - } else { - final Drawable d = res.getDrawable(R.drawable.attribute_unknown); - iv.setImageDrawable(d); - } - - attributeRow.addView(fl); - } - - return rows; - } - - private LinearLayout newAttributeIconsRow() { - final LinearLayout rowLayout = new LinearLayout(CacheDetailActivity.this); - rowLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.WRAP_CONTENT)); - rowLayout.setOrientation(LinearLayout.HORIZONTAL); - return rowLayout; - } - - private ViewGroup createAttributeDescriptionsLayout(final LinearLayout parentView) { - final LinearLayout descriptions = (LinearLayout) getLayoutInflater().inflate( - R.layout.attribute_descriptions, parentView, false); - final TextView attribView = (TextView) descriptions.getChildAt(0); - - final StringBuilder buffer = new StringBuilder(); - for (String attributeName : cache.getAttributes()) { - final boolean enabled = CacheAttribute.isEnabled(attributeName); - // search for a translation of the attribute - final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName)); - if (attrib != null) { - attributeName = attrib.getL10n(enabled); - } - if (buffer.length() > 0) { - buffer.append('\n'); - } - buffer.append(attributeName); - } - - attribView.setText(buffer); - - return descriptions; - } - } - private void refreshCache() { if (progress.isShowing()) { showToast(res.getString(R.string.err_detail_still_working)); return; } - if (!Network.isNetworkConnected(getApplicationContext())) { + if (!Network.isNetworkConnected()) { showToast(getString(R.string.err_server)); return; } @@ -883,7 +765,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc progress.show(this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage()); - cache.refresh(refreshCacheHandler, RxUtils.networkScheduler); + cache.refresh(refreshCacheHandler, RxUtils.refreshScheduler); } private void dropCache() { @@ -893,7 +775,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } progress.show(this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null); - cache.drop(new ChangeNotificationHandler(this, progress), RxUtils.networkScheduler); + cache.drop(new ChangeNotificationHandler(this, progress)); } private void storeCache() { @@ -910,9 +792,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc public void call(final Integer selectedListId) { storeCache(selectedListId, new StoreCacheHandler(CacheDetailActivity.this, progress)); } - }, true, StoredList.TEMPORARY_LIST_ID); + }, true, StoredList.TEMPORARY_LIST.id); } else { - storeCache(StoredList.TEMPORARY_LIST_ID, new StoreCacheHandler(this, progress)); + storeCache(StoredList.TEMPORARY_LIST.id, new StoreCacheHandler(this, progress)); } } @@ -920,12 +802,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc * Creator for details-view. */ private class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> { - /** - * Reference to the details list, so that the helper-method can access it without an additional argument - */ + // Reference to the details list and favorite line, so that the helper-method can access them without an additional argument private LinearLayout detailsList; - - private Thread watchlistThread; + private ImmutablePair<RelativeLayout, TextView> favoriteLine; @Override public ScrollView getDispatchedView(final ViewGroup parentView) { @@ -937,7 +816,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc view = (ScrollView) getLayoutInflater().inflate(R.layout.cachedetail_details_page, parentView, false); // Start loading preview map - AndroidObservable.bindActivity(CacheDetailActivity.this, previewMap).subscribeOn(RxUtils.networkScheduler) + AppObservable.bindActivity(CacheDetailActivity.this, previewMap).subscribeOn(RxUtils.networkScheduler) .subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable image) { @@ -962,10 +841,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc span.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - addContextMenu(details.add(R.string.cache_name, span)); + addContextMenu(details.add(R.string.cache_name, span).right); details.add(R.string.cache_type, cache.getType().getL10n()); details.addSize(cache); - addContextMenu(details.add(R.string.cache_geocode, cache.getGeocode())); + addContextMenu(details.add(R.string.cache_geocode, cache.getGeocode()).right); details.addCacheState(cache); details.addDistance(cache, cacheDistanceView); @@ -976,9 +855,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc details.addRating(cache); // favorite count - if (cache.getFavoritePoints() > 0) { - details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×"); - } + favoriteLine = details.add(R.string.cache_favorite, ""); // own rating if (cache.getMyVote() > 0) { @@ -987,7 +864,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // cache author if (StringUtils.isNotBlank(cache.getOwnerDisplayName()) || StringUtils.isNotBlank(cache.getOwnerUserId())) { - final TextView ownerView = details.add(R.string.cache_owner, ""); + final TextView ownerView = details.add(R.string.cache_owner, "").right; if (StringUtils.isNotBlank(cache.getOwnerDisplayName())) { ownerView.setText(cache.getOwnerDisplayName(), TextView.BufferType.SPANNABLE); } else { // OwnerReal guaranteed to be not blank based on above @@ -1009,17 +886,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // cache coordinates if (cache.getCoords() != null) { - final TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString()); + final TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString()).right; valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords())); addContextMenu(valueView); } // cache attributes - if (!cache.getAttributes().isEmpty()) { - final LinearLayout innerLayout = ButterKnife.findById(view, R.id.attributes_innerbox); - new AttributeViewBuilder().fillView(innerLayout); - view.findViewById(R.id.attributes_box).setVisibility(View.VISIBLE); - } + updateAttributesText(); + updateAttributesIcons(); + ButterKnife.findById(view, R.id.attributes_box).setVisibility(cache.getAttributes().isEmpty() ? View.GONE : View.VISIBLE); updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener()); @@ -1058,6 +933,61 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return view; } + private void updateAttributesIcons() { + final GridView gridView = ButterKnife.findById(view, R.id.attributes_grid); + final List<String> attributes = cache.getAttributes(); + if (attributes.isEmpty()) { + gridView.setVisibility(View.GONE); + return; + } + gridView.setAdapter(new AttributesGridAdapter(CacheDetailActivity.this, cache)); + gridView.setVisibility(View.VISIBLE); + gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(final android.widget.AdapterView<?> parent, final View view, final int position, final long id) { + toggleAttributesView(); + } + }); + } + + protected void toggleAttributesView() { + final View textView = ButterKnife.findById(view, R.id.attributes_text); + textView.setVisibility(textView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE); + final View gridView = ButterKnife.findById(view, R.id.attributes_grid); + gridView.setVisibility(gridView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE); + } + + private void updateAttributesText() { + final TextView attribView = ButterKnife.findById(view, R.id.attributes_text); + final List<String> attributes = cache.getAttributes(); + if (attributes.isEmpty()) { + attribView.setVisibility(View.GONE); + return; + } + final StringBuilder text = new StringBuilder(); + for (String attributeName : attributes) { + final boolean enabled = CacheAttribute.isEnabled(attributeName); + // search for a translation of the attribute + final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName)); + if (attrib != null) { + attributeName = attrib.getL10n(enabled); + } + if (text.length() > 0) { + text.append('\n'); + } + text.append(attributeName); + } + attribView.setText(text); + attribView.setVisibility(View.GONE); + attribView.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(final View v) { + toggleAttributesView(); + } + }); + } + private class StoreCacheClickListener implements View.OnClickListener { @Override public void onClick(final View arg0) { @@ -1083,164 +1013,133 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc /** * Abstract Listener for add / remove buttons for watchlist */ - private abstract class AbstractWatchlistClickListener implements View.OnClickListener { - public void doExecute(final int titleId, final int messageId, final Thread thread) { + private abstract class AbstractPropertyListener implements View.OnClickListener { + + private final SimpleCancellableHandler handler = new SimpleCancellableHandler(CacheDetailActivity.this, progress) { + @Override + public void handleRegularMessage(final Message message) { + super.handleRegularMessage(message); + updateWatchlistBox(); + updateFavPointBox(); + } + }; + + public void doExecute(final int titleId, final int messageId, final Action1<SimpleCancellableHandler> action) { if (progress.isShowing()) { showToast(res.getString(R.string.err_watchlist_still_managing)); return; } progress.show(CacheDetailActivity.this, res.getString(titleId), res.getString(messageId), true, null); - - if (watchlistThread != null) { - watchlistThread.interrupt(); - } - - watchlistThread = thread; - watchlistThread.start(); + RxUtils.networkScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + action.call(handler); + } + }); } } /** * Listener for "add to watchlist" button */ - private class AddToWatchlistClickListener extends AbstractWatchlistClickListener { + private class AddToWatchlistClickListener extends AbstractPropertyListener { @Override public void onClick(final View arg0) { doExecute(R.string.cache_dialog_watchlist_add_title, R.string.cache_dialog_watchlist_add_message, - new WatchlistAddThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress))); + new Action1<SimpleCancellableHandler>() { + @Override + public void call(final SimpleCancellableHandler simpleCancellableHandler) { + watchListAdd(simpleCancellableHandler); + } + }); } } /** * Listener for "remove from watchlist" button */ - private class RemoveFromWatchlistClickListener extends AbstractWatchlistClickListener { + private class RemoveFromWatchlistClickListener extends AbstractPropertyListener { @Override public void onClick(final View arg0) { doExecute(R.string.cache_dialog_watchlist_remove_title, R.string.cache_dialog_watchlist_remove_message, - new WatchlistRemoveThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress))); + new Action1<SimpleCancellableHandler>() { + @Override + public void call(final SimpleCancellableHandler simpleCancellableHandler) { + watchListRemove(simpleCancellableHandler); + } + }); } } - /** Thread to add this cache to the watchlist of the user */ - private class WatchlistAddThread extends Thread { - private final Handler handler; - - public WatchlistAddThread(final Handler handler) { - this.handler = handler; - } - - @Override - public void run() { - watchlistThread = null; - Message msg; - if (ConnectorFactory.getConnector(cache).addToWatchlist(cache)) { - msg = Message.obtain(handler, MESSAGE_SUCCEEDED); - } else { - msg = Message.obtain(handler, MESSAGE_FAILED); - final Bundle bundle = new Bundle(); - bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_watchlist_failed)); - msg.setData(bundle); - } - handler.sendMessage(msg); + /** Add this cache to the watchlist of the user */ + private void watchListAdd(final SimpleCancellableHandler handler) { + if (ConnectorFactory.getConnector(cache).addToWatchlist(cache)) { + handler.obtainMessage(MESSAGE_SUCCEEDED).sendToTarget(); + } else { + handler.sendTextMessage(MESSAGE_FAILED, R.string.err_watchlist_failed); } } - /** Thread to remove this cache from the watchlist of the user */ - private class WatchlistRemoveThread extends Thread { - private final Handler handler; - - public WatchlistRemoveThread(final Handler handler) { - this.handler = handler; - } - - @Override - public void run() { - watchlistThread = null; - Message msg; - if (ConnectorFactory.getConnector(cache).removeFromWatchlist(cache)) { - msg = Message.obtain(handler, MESSAGE_SUCCEEDED); - } else { - msg = Message.obtain(handler, MESSAGE_FAILED); - final Bundle bundle = new Bundle(); - bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_watchlist_failed)); - msg.setData(bundle); - } - handler.sendMessage(msg); + /** Remove this cache from the watchlist of the user */ + private void watchListRemove(final SimpleCancellableHandler handler) { + if (ConnectorFactory.getConnector(cache).removeFromWatchlist(cache)) { + handler.obtainMessage(MESSAGE_SUCCEEDED).sendToTarget(); + } else { + handler.sendTextMessage(MESSAGE_FAILED, R.string.err_watchlist_failed); } } - /** Thread to add this cache to the favorite list of the user */ - private class FavoriteAddThread extends Thread { - private final Handler handler; - - public FavoriteAddThread(final Handler handler) { - this.handler = handler; - } - - @Override - public void run() { - watchlistThread = null; - Message msg; - if (GCConnector.addToFavorites(cache)) { - msg = Message.obtain(handler, MESSAGE_SUCCEEDED); - } else { - msg = Message.obtain(handler, MESSAGE_FAILED); - final Bundle bundle = new Bundle(); - bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_favorite_failed)); - msg.setData(bundle); - } - handler.sendMessage(msg); + /** Add this cache to the favorite list of the user */ + private void favoriteAdd(final SimpleCancellableHandler handler) { + if (GCConnector.addToFavorites(cache)) { + handler.obtainMessage(MESSAGE_SUCCEEDED).sendToTarget(); + } else { + handler.sendTextMessage(MESSAGE_FAILED, R.string.err_favorite_failed); } } - /** Thread to remove this cache to the favorite list of the user */ - private class FavoriteRemoveThread extends Thread { - private final Handler handler; - - public FavoriteRemoveThread(final Handler handler) { - this.handler = handler; - } - - @Override - public void run() { - watchlistThread = null; - Message msg; - if (GCConnector.removeFromFavorites(cache)) { - msg = Message.obtain(handler, MESSAGE_SUCCEEDED); - } else { - msg = Message.obtain(handler, MESSAGE_FAILED); - final Bundle bundle = new Bundle(); - bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, res.getString(R.string.err_favorite_failed)); - msg.setData(bundle); - } - handler.sendMessage(msg); + /** Remove this cache to the favorite list of the user */ + private void favoriteRemove(final SimpleCancellableHandler handler) { + if (GCConnector.removeFromFavorites(cache)) { + handler.obtainMessage(MESSAGE_SUCCEEDED).sendToTarget(); + } else { + handler.sendTextMessage(MESSAGE_FAILED, R.string.err_favorite_failed); } } /** * Listener for "add to favorites" button */ - private class FavoriteAddClickListener extends AbstractWatchlistClickListener { + private class FavoriteAddClickListener extends AbstractPropertyListener { @Override public void onClick(final View arg0) { doExecute(R.string.cache_dialog_favorite_add_title, R.string.cache_dialog_favorite_add_message, - new FavoriteAddThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress))); + new Action1<SimpleCancellableHandler>() { + @Override + public void call(final SimpleCancellableHandler simpleCancellableHandler) { + favoriteAdd(simpleCancellableHandler); + } + }); } } /** * Listener for "remove from favorites" button */ - private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener { + private class FavoriteRemoveClickListener extends AbstractPropertyListener { @Override public void onClick(final View arg0) { doExecute(R.string.cache_dialog_favorite_remove_title, R.string.cache_dialog_favorite_remove_message, - new FavoriteRemoveThread(new SimpleUpdateHandler(CacheDetailActivity.this, progress))); + new Action1<SimpleCancellableHandler>() { + @Override + public void call(final SimpleCancellableHandler simpleCancellableHandler) { + favoriteRemove(simpleCancellableHandler); + } + }); } } @@ -1249,7 +1148,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc */ private class ChangeListClickListener implements View.OnClickListener { @Override - public void onClick(final View view) { + public void onClick(final View v) { new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title, new Action1<Integer>() { @Override @@ -1277,7 +1176,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } /** - * shows/hides buttons, sets text in watchlist box + * Show/hide buttons, set text in watchlist box */ private void updateWatchlistBox() { final LinearLayout layout = ButterKnife.findById(view, R.id.watchlist_box); @@ -1307,13 +1206,20 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc buttonRemove.setEnabled(false); buttonRemove.setVisibility(View.GONE); } - } /** - * shows/hides buttons, sets text in watchlist box + * Show/hide buttons, set text in favorite line and box */ private void updateFavPointBox() { + // Favorite counts + if (cache.getFavoritePoints() > 0) { + favoriteLine.left.setVisibility(View.VISIBLE); + favoriteLine.right.setText(cache.getFavoritePoints() + "×"); + } else { + favoriteLine.left.setVisibility(View.GONE); + } + final LinearLayout layout = ButterKnife.findById(view, R.id.favpoint_box); final boolean supportsFavoritePoints = cache.supportsFavoritePoints(); layout.setVisibility(supportsFavoritePoints ? View.VISIBLE : View.GONE); @@ -1356,12 +1262,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // update text final TextView text = ButterKnife.findById(view, R.id.list_text); final StoredList list = DataStore.getList(cache.getListId()); - if (list != null) { - text.setText(res.getString(R.string.cache_list_text) + " " + list.title); - } else { - // this should not happen - text.setText(R.string.cache_list_unknown); - } + text.setText(res.getString(R.string.cache_list_text) + " " + list.title); } else { // hide box box.setVisibility(View.GONE); @@ -1395,6 +1296,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc }); + /** + * Reflect the (contextual) action mode of the action bar. + */ + protected ActionMode currentActionMode; + protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @InjectView(R.id.personalnote) protected TextView personalNoteView; @@ -1517,19 +1423,26 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc return view; } - Thread currentThread; - private void uploadPersonalNote() { final SimpleCancellableHandler myHandler = new SimpleCancellableHandler(CacheDetailActivity.this, progress); final Message cancelMessage = myHandler.cancelMessage(res.getString(R.string.cache_personal_note_upload_cancelled)); progress.show(CacheDetailActivity.this, res.getString(R.string.cache_personal_note_uploading), res.getString(R.string.cache_personal_note_uploading), true, cancelMessage); - if (currentThread != null) { - currentThread.interrupt(); - } - currentThread = new UploadPersonalNoteThread(cache, myHandler); - currentThread.start(); + myHandler.unsubscribeIfCancelled(RxUtils.networkScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final IConnector con = ConnectorFactory.getConnector(cache); + if (con.supportsPersonalNote()) { + con.uploadPersonalNote(cache); + } + final Message msg = Message.obtain(); + final Bundle bundle = new Bundle(); + bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, CgeoApplication.getInstance().getString(R.string.cache_personal_note_upload_done)); + msg.setData(bundle); + myHandler.sendMessage(msg); + } + })); } private void loadLongDescription() { @@ -1563,9 +1476,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (unknownTagsHandler.isProblematicDetected()) { final int startPos = description.length(); final IConnector connector = ConnectorFactory.getConnector(cache); - final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); - ((Editable) description).append("\n\n").append(tableNote); - ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (StringUtils.isNotEmpty(cache.getUrl())) { + final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); + ((Editable) description).append("\n\n").append(tableNote); + ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } } /** @@ -1597,13 +1512,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (null != loadingIndicatorView) { loadingIndicatorView.setVisibility(View.GONE); } - } catch (final Exception e) { + } catch (final Exception ignored) { showToast(res.getString(R.string.err_load_descr_failed)); } } private static void fixTextColor(final String descriptionString, final IndexOutOfBoundsAvoidingTextView descriptionView) { - int backcolor; + final int backcolor; if (Settings.isLightSkin()) { backcolor = color.white; @@ -1653,12 +1568,18 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (!cache.isOffline()) { showToast(getString(R.string.info_cache_saved)); cache.setListId(StoredList.STANDARD_LIST_ID); - DataStore.saveCache(cache, LoadFlags.SAVE_ALL); + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(final Void... params) { + DataStore.saveCache(cache, LoadFlags.SAVE_ALL); + return null; + } + }.execute(); } } private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ListView> { - private final int VISITED_INSET = (int) (6.6f * CgeoApplication.getInstance().getResources().getDisplayMetrics().density + 0.5f); + private final int visitedInset = (int) (6.6f * CgeoApplication.getInstance().getResources().getDisplayMetrics().density + 0.5f); @Override public ListView getDispatchedView(final ViewGroup parentView) { @@ -1741,15 +1662,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } else { nameView.setText(res.getString(R.string.waypoint)); } - setWaypointIcon(res, nameView, wpt); + setWaypointIcon(nameView, wpt); // visited if (wpt.isVisited()) { - final TypedValue a = new TypedValue(); - getTheme().resolveAttribute(R.attr.text_color_grey, a, true); - if (a.type >= TypedValue.TYPE_FIRST_COLOR_INT && a.type <= TypedValue.TYPE_LAST_COLOR_INT) { + final TypedValue typedValue = new TypedValue(); + getTheme().resolveAttribute(R.attr.text_color_grey, typedValue, true); + if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) { // really should be just a color! - nameView.setTextColor(a.data); + nameView.setTextColor(typedValue.data); } } @@ -1759,7 +1680,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc noteView.setOnClickListener(new DecryptTextClickListener(noteView)); noteView.setVisibility(View.VISIBLE); if (TextUtils.containsHtml(wpt.getNote())) { - noteView.setText(Html.fromHtml(wpt.getNote()), TextView.BufferType.SPANNABLE); + noteView.setText(Html.fromHtml(wpt.getNote(), new SmileyImage(cache.getGeocode(), noteView), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE); } else { noteView.setText(wpt.getNote()); @@ -1805,15 +1726,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc }); } - private void setWaypointIcon(final Resources res, final TextView nameView, final Waypoint wpt) { + private void setWaypointIcon(final TextView nameView, final Waypoint wpt) { final WaypointType waypointType = wpt.getWaypointType(); final Drawable icon; if (wpt.isVisited()) { final LayerDrawable ld = new LayerDrawable(new Drawable[] { res.getDrawable(waypointType.markerId), res.getDrawable(R.drawable.tick) }); - ld.setLayerInset(0, 0, 0, VISITED_INSET, VISITED_INSET); - ld.setLayerInset(1, VISITED_INSET, VISITED_INSET, 0, 0); + ld.setLayerInset(0, 0, 0, visitedInset, visitedInset); + ld.setLayerInset(1, visitedInset, visitedInset, 0, 0); icon = ld; } else { icon = res.getDrawable(waypointType.markerId); @@ -1880,10 +1801,14 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onLongClick(final View v) { - startSupportActionMode(new ActionMode.Callback() { + currentActionMode = startSupportActionMode(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) { + return prepareClipboardActionMode(view, actionMode, menu); + } + + private boolean prepareClipboardActionMode(final View view, final ActionMode actionMode, final Menu menu) { switch (view.getId()) { case R.id.value: // coordinates, gc-code, name assert view instanceof TextView; @@ -1892,29 +1817,25 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc buildDetailsContextMenu(actionMode, menu, itemTitle, true); return true; case R.id.shortdesc: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); + clickedItemText = cache.getShortDescription(); buildDetailsContextMenu(actionMode, menu, res.getString(R.string.cache_description), false); return true; case R.id.longdesc: - assert view instanceof TextView; // combine short and long description final String shortDesc = cache.getShortDescription(); if (StringUtils.isBlank(shortDesc)) { - clickedItemText = ((TextView) view).getText(); + clickedItemText = cache.getDescription(); } else { - clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText(); + clickedItemText = shortDesc + "\n\n" + cache.getDescription(); } buildDetailsContextMenu(actionMode, menu, res.getString(R.string.cache_description), false); return true; case R.id.personalnote: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); + clickedItemText = cache.getPersonalNote(); buildDetailsContextMenu(actionMode, menu, res.getString(R.string.cache_personal_note), true); return true; case R.id.hint: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); + clickedItemText = cache.getHint(); buildDetailsContextMenu(actionMode, menu, res.getString(R.string.cache_hint), false); return true; case R.id.log: @@ -1923,8 +1844,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc buildDetailsContextMenu(actionMode, menu, res.getString(R.string.cache_logs), false); return true; case R.id.date: // event date - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); + clickedItemText = Formatter.formatHiddenDate(cache); buildDetailsContextMenu(actionMode, menu, res.getString(R.string.cache_event), true); menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar()); return true; @@ -1934,13 +1854,13 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public void onDestroyActionMode(final ActionMode actionMode) { - // do nothing + currentActionMode = null; } @Override public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) { actionMode.getMenuInflater().inflate(R.menu.details_context, menu); - + prepareClipboardActionMode(view, actionMode, menu); // Return true so that the action mode is shown return true; } @@ -1974,7 +1894,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc /** * A dialog to allow the user to select reseting coordinates local/remote/both. */ - private AlertDialog createResetCacheCoordinatesDialog(final Geocache cache, final Waypoint wpt) { + private AlertDialog createResetCacheCoordinatesDialog(final Waypoint wpt) { final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.waypoint_reset_cache_coords); @@ -1987,13 +1907,16 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc dialog.dismiss(); final ProgressDialog progressDialog = ProgressDialog.show(CacheDetailActivity.this, getString(R.string.cache), getString(R.string.waypoint_reset), true); final HandlerResetCoordinates handler = new HandlerResetCoordinates(CacheDetailActivity.this, progressDialog, which == 1); - new ResetCoordsThread(cache, handler, wpt, which == 0 || which == 1, which == 1, progressDialog).start(); + resetCoords(cache, handler, wpt, which == 0 || which == 1, which == 1, progressDialog); } }); return builder.create(); } private static class HandlerResetCoordinates extends WeakReferenceHandler<CacheDetailActivity> { + public static final int LOCAL = 0; + public static final int ON_WEBSITE = 1; + private boolean remoteFinished = false; private boolean localFinished = false; private final ProgressDialog progressDialog; @@ -2007,7 +1930,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public void handleMessage(final Message msg) { - if (msg.what == ResetCoordsThread.LOCAL) { + if (msg.what == LOCAL) { localFinished = true; } else { remoteFinished = true; @@ -2024,94 +1947,53 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } - private class ResetCoordsThread extends Thread { - - private final Geocache cache; - private final Handler handler; - private final boolean local; - private final boolean remote; - private final Waypoint wpt; - private final ProgressDialog progress; - public static final int LOCAL = 0; - public static final int ON_WEBSITE = 1; - - public ResetCoordsThread(final Geocache cache, final Handler handler, final Waypoint wpt, final boolean local, final boolean remote, final ProgressDialog progress) { - this.cache = cache; - this.handler = handler; - this.local = local; - this.remote = remote; - this.wpt = wpt; - this.progress = progress; - } - - @Override - public void run() { - - if (local) { - runOnUiThread(new Runnable() { - @Override - public void run() { - progress.setMessage(res.getString(R.string.waypoint_reset_cache_coords)); - } - }); - cache.setCoords(wpt.getCoords()); - cache.setUserModifiedCoords(false); - cache.deleteWaypointForce(wpt); - DataStore.saveChangedCache(cache); - handler.sendEmptyMessage(LOCAL); - } - - final IConnector con = ConnectorFactory.getConnector(cache); - if (remote && con.supportsOwnCoordinates()) { - runOnUiThread(new Runnable() { - @Override - public void run() { - progress.setMessage(res.getString(R.string.waypoint_coordinates_being_reset_on_website)); - } - }); - - final boolean result = con.deleteModifiedCoordinates(cache); - - runOnUiThread(new Runnable() { + private void resetCoords(final Geocache cache, final Handler handler, final Waypoint wpt, final boolean local, final boolean remote, final ProgressDialog progress) { + RxUtils.networkScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + if (local) { + runOnUiThread(new Runnable() { + @Override + public void run() { + progress.setMessage(res.getString(R.string.waypoint_reset_cache_coords)); + } + }); + cache.setCoords(wpt.getCoords()); + cache.setUserModifiedCoords(false); + cache.deleteWaypointForce(wpt); + DataStore.saveChangedCache(cache); + handler.sendEmptyMessage(HandlerResetCoordinates.LOCAL); + } - @Override - public void run() { - if (result) { - showToast(getString(R.string.waypoint_coordinates_has_been_reset_on_website)); - } else { - showToast(getString(R.string.waypoint_coordinates_upload_error)); + final IConnector con = ConnectorFactory.getConnector(cache); + if (remote && con.supportsOwnCoordinates()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + progress.setMessage(res.getString(R.string.waypoint_coordinates_being_reset_on_website)); } - handler.sendEmptyMessage(ON_WEBSITE); - notifyDataSetChanged(); - } + }); - }); + final boolean result = con.deleteModifiedCoordinates(cache); - } - } - } + runOnUiThread(new Runnable() { - private static class UploadPersonalNoteThread extends Thread { - private Geocache cache = null; - private CancellableHandler handler = null; + @Override + public void run() { + if (result) { + showToast(getString(R.string.waypoint_coordinates_has_been_reset_on_website)); + } else { + showToast(getString(R.string.waypoint_coordinates_upload_error)); + } + handler.sendEmptyMessage(HandlerResetCoordinates.ON_WEBSITE); + notifyDataSetChanged(); + } - public UploadPersonalNoteThread(final Geocache cache, final CancellableHandler handler) { - this.cache = cache; - this.handler = handler; - } + }); - @Override - public void run() { - final IConnector con = ConnectorFactory.getConnector(cache); - if (con.supportsPersonalNote()) { - con.uploadPersonalNote(cache); + } } - final Message msg = Message.obtain(); - final Bundle bundle = new Bundle(); - bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, CgeoApplication.getInstance().getString(R.string.cache_personal_note_upload_done)); - msg.setData(bundle); - handler.sendMessage(msg); - } + }); } @Override @@ -2186,7 +2068,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (cache.isOffline()) { final long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes - String ago; + final String ago; if (diff < 15) { ago = res.getString(R.string.cache_offline_time_mins_few); } else if (diff < 50) { @@ -2232,7 +2114,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg(R.string.cache_dialog_offline_save_message, (String) msg.obj); } else { - notifyDatasetChanged(activityRef); + notifyDataSetChanged(activityRef); } } } @@ -2248,7 +2130,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg(R.string.cache_dialog_refresh_message, (String) msg.obj); } else { - notifyDatasetChanged(activityRef); + notifyDataSetChanged(activityRef); } } } @@ -2261,27 +2143,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public void handleMessage(final Message msg) { - notifyDatasetChanged(activityRef); - } - } - - private static final class SimpleUpdateHandler extends SimpleHandler { - - public SimpleUpdateHandler(final CacheDetailActivity activity, final Progress progress) { - super(activity, progress); - } - - @Override - public void handleMessage(final Message msg) { - if (msg.what == MESSAGE_FAILED) { - super.handleMessage(msg); - } else { - notifyDatasetChanged(activityRef); - } + notifyDataSetChanged(activityRef); } } - private static void notifyDatasetChanged(final WeakReference<AbstractActivity> activityRef) { + private static void notifyDataSetChanged(final WeakReference<AbstractActivity> activityRef) { final CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get()); if (activity != null) { activity.notifyDataSetChanged(); @@ -2308,18 +2174,29 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public void onFinishEditNoteDialog(final String note) { - cache.setPersonalNote(note); - cache.parseWaypointsFromNote(); final TextView personalNoteView = ButterKnife.findById(this, R.id.personalnote); setPersonalNote(personalNoteView, note); - DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); - notifyDataSetChanged(); + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(final Void... params) { + cache.setPersonalNote(note); + cache.parseWaypointsFromNote(); + DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); + return null; + } + + @Override + protected void onPostExecute(final Void v) { + notifyDataSetChanged(); + } + }.execute(); } private static void setPersonalNote(final TextView personalNoteView, final String personalNote) { personalNoteView.setText(personalNote, TextView.BufferType.SPANNABLE); if (StringUtils.isNotBlank(personalNote)) { personalNoteView.setVisibility(View.VISIBLE); + Linkify.addLinks(personalNoteView, Linkify.ALL); } else { personalNoteView.setVisibility(View.GONE); } @@ -2337,6 +2214,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public void cachesAround() { - CacheListActivity.startActivityCoordinates(this, cache.getCoords()); + CacheListActivity.startActivityCoordinates(this, cache.getCoords(), cache.getName()); + } + + public void setNeedsRefresh() { + refreshOnResume = true; } } diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java index 522004e..bedb737 100644 --- a/main/src/cgeo/geocaching/CacheListActivity.java +++ b/main/src/cgeo/geocaching/CacheListActivity.java @@ -9,7 +9,9 @@ import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.apps.cachelist.CacheListAppFactory; +import cgeo.geocaching.apps.cachelist.CacheListApp; +import cgeo.geocaching.apps.cachelist.CacheListApps; +import cgeo.geocaching.apps.cachelist.ListNavigationSelectionActionProvider; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.gc.RecaptchaHandler; import cgeo.geocaching.enumerations.CacheListType; @@ -19,15 +21,14 @@ import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.export.FieldnoteExport; import cgeo.geocaching.export.GpxExport; import cgeo.geocaching.files.GPXImporter; -import cgeo.geocaching.filter.FilterUserInterface; +import cgeo.geocaching.filter.FilterActivity; import cgeo.geocaching.filter.IFilter; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.list.AbstractList; +import cgeo.geocaching.list.ListNameMemento; import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.loaders.AbstractSearchLoader; import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType; -import cgeo.geocaching.loaders.AddressGeocacheListLoader; import cgeo.geocaching.loaders.CoordsGeocacheListLoader; import cgeo.geocaching.loaders.FinderGeocacheListLoader; import cgeo.geocaching.loaders.HistoryGeocacheListLoader; @@ -36,14 +37,15 @@ import cgeo.geocaching.loaders.NextPageGeocacheListLoader; import cgeo.geocaching.loaders.OfflineGeocacheListLoader; import cgeo.geocaching.loaders.OwnerGeocacheListLoader; import cgeo.geocaching.loaders.PocketGeocacheListLoader; -import cgeo.geocaching.loaders.RemoveFromHistoryLoader; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.network.Cookies; +import cgeo.geocaching.network.DownloadProgress; import cgeo.geocaching.network.Network; -import cgeo.geocaching.network.Parameters; -import cgeo.geocaching.sensors.DirectionProvider; +import cgeo.geocaching.network.Send2CgeoDownloader; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.SettingsActivity; import cgeo.geocaching.sorting.CacheComparator; @@ -52,25 +54,33 @@ import cgeo.geocaching.ui.CacheListAdapter; import cgeo.geocaching.ui.LoggingUI; import cgeo.geocaching.ui.WeakReferenceHandler; import cgeo.geocaching.ui.dialog.Dialogs; +import cgeo.geocaching.utils.AngleUtils; import cgeo.geocaching.utils.AsyncTaskWithProgress; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.CancellableHandler; -import cgeo.geocaching.utils.DateUtils; import cgeo.geocaching.utils.Log; - -import ch.boye.httpclientandroidlib.HttpResponse; +import cgeo.geocaching.utils.RxUtils; import com.github.amlcurran.showcaseview.targets.ActionViewTarget; import com.github.amlcurran.showcaseview.targets.ActionViewTarget.Type; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import rx.Observable; +import rx.Observable.OnSubscribe; +import rx.Scheduler.Worker; +import rx.Subscriber; import rx.Subscription; +import rx.functions.Action0; import rx.functions.Action1; +import rx.functions.Func1; import rx.schedulers.Schedulers; +import rx.subjects.ReplaySubject; +import rx.subscriptions.CompositeSubscription; +import rx.subscriptions.Subscriptions; import android.app.Activity; import android.app.AlertDialog; @@ -83,6 +93,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -104,21 +115,15 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; public class CacheListActivity extends AbstractListActivity implements FilteredActivity, LoaderManager.LoaderCallbacks<SearchResult> { private static final int MAX_LIST_ITEMS = 1000; - private static final int MSG_DONE = -1; - private static final int MSG_SERVER_FAIL = -2; - private static final int MSG_NO_REGISTRATION = -3; - private static final int MSG_WAITING = 0; - private static final int MSG_LOADING = 1; - private static final int MSG_LOADED = 2; - private static final int REQUEST_CODE_IMPORT_GPX = 1; private CacheListType type = null; @@ -132,30 +137,28 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA private final Progress progress = new Progress(); private String title = ""; private int detailTotal = 0; - private int detailProgress = 0; + private final AtomicInteger detailProgress = new AtomicInteger(0); private long detailProgressTime = 0L; - private int listId = StoredList.TEMPORARY_LIST_ID; // Only meaningful for the OFFLINE type + private int listId = StoredList.TEMPORARY_LIST.id; // Only meaningful for the OFFLINE type private final GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override public void updateDirection(final float direction) { if (Settings.isLiveList()) { - adapter.setActualHeading(DirectionProvider.getDirectionNow(direction)); + adapter.setActualHeading(AngleUtils.getDirectionNow(direction)); } } @Override - public void updateGeoData(final IGeoData geoData) { - final Geopoint coords = geoData.getCoords(); - if (coords != null) { - adapter.setActualCoordinates(coords); - } + public void updateGeoData(final GeoData geoData) { + adapter.setActualCoordinates(geoData.getCoords()); } }; private ContextMenuInfo lastMenuInfo; private String contextMenuGeocode = ""; private Subscription resumeSubscription; + private final ListNameMemento listNameMemento = new ListNameMemento(); // FIXME: This method has mostly been replaced by the loaders. But it still contains a license agreement check. public void handleCachesLoaded() { @@ -276,42 +279,49 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA refreshSpinnerAdapter(); } - private final CancellableHandler loadDetailsHandler = new CancellableHandler() { + private class LoadDetailsHandler extends CancellableHandler { @Override public void handleRegularMessage(final Message msg) { updateAdapter(); - if (msg.what > -1) { - cacheList.get(msg.what).setStatusChecked(false); + if (msg.what == DownloadProgress.MSG_LOADED) { + ((Geocache) msg.obj).setStatusChecked(false); adapter.notifyDataSetChanged(); + final int dp = detailProgress.get(); final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); - final int minutesRemaining = ((detailTotal - detailProgress) * secondsElapsed / ((detailProgress > 0) ? detailProgress : 1) / 60); + final int minutesRemaining = ((detailTotal - dp) * secondsElapsed / ((dp > 0) ? dp : 1) / 60); - progress.setProgress(detailProgress); + progress.setProgress(dp); if (minutesRemaining < 1) { progress.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm)); } else { progress.setMessage(res.getString(R.string.caches_downloading) + " " + res.getQuantityString(R.plurals.caches_eta_mins, minutesRemaining, minutesRemaining)); } } else { - if (search != null) { - final Set<Geocache> cacheListTmp = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); - if (CollectionUtils.isNotEmpty(cacheListTmp)) { - cacheList.clear(); - cacheList.addAll(cacheListTmp); + new AsyncTask<Void, Void, Set<Geocache>>() { + @Override + protected Set<Geocache> doInBackground(final Void... params) { + return search != null ? search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB) : null; } - } - setAdapterCurrentCoordinates(false); + @Override + protected void onPostExecute(final Set<Geocache> result) { + if (CollectionUtils.isNotEmpty(result)) { + cacheList.clear(); + cacheList.addAll(result); + } + setAdapterCurrentCoordinates(false); - showProgress(false); - progress.dismiss(); + showProgress(false); + progress.dismiss(); + } + }.execute(); } } - }; + } /** * TODO Possibly parts should be a Thread not a Handler @@ -324,22 +334,22 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA adapter.notifyDataSetChanged(); switch (msg.what) { - case MSG_WAITING: //no caches + case DownloadProgress.MSG_WAITING: //no caches progress.setMessage(res.getString(R.string.web_import_waiting)); break; - case MSG_LOADING: //cache downloading + case DownloadProgress.MSG_LOADING: //cache downloading progress.setMessage(res.getString(R.string.web_downloading) + " " + msg.obj + '…'); break; - case MSG_LOADED: //Cache downloaded + case DownloadProgress.MSG_LOADED: //Cache downloaded progress.setMessage(res.getString(R.string.web_downloaded) + " " + msg.obj + '…'); refreshCurrentList(); break; - case MSG_SERVER_FAIL: + case DownloadProgress.MSG_SERVER_FAIL: progress.dismiss(); showToast(res.getString(R.string.sendToCgeo_download_fail)); finish(); break; - case MSG_NO_REGISTRATION: + case DownloadProgress.MSG_NO_REGISTRATION: progress.dismiss(); showToast(res.getString(R.string.sendToCgeo_no_registration)); finish(); @@ -374,7 +384,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } }; private AbstractSearchLoader currentLoader; - private String newListName = StringUtils.EMPTY; public CacheListActivity() { super(true); @@ -392,8 +401,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA // get parameters Bundle extras = getIntent().getExtras(); if (extras != null) { - final Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE); - type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE; + type = Intents.getListType(getIntent()); coords = extras.getParcelable(Intents.EXTRA_COORDS); } else { @@ -405,6 +413,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA coords = Geopoint.ZERO; } } + if (type == CacheListType.NEAREST) { + coords = Sensors.getInstance().currentGeo().getCoords(); + } setTitle(title); @@ -513,7 +524,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA public void onResume() { super.onResume(); - resumeSubscription = geoDirHandler.start(GeoDirHandler.UPDATE_GEODATA | GeoDirHandler.UPDATE_DIRECTION); + resumeSubscription = geoDirHandler.start(GeoDirHandler.UPDATE_GEODATA | GeoDirHandler.UPDATE_DIRECTION | GeoDirHandler.LOW_POWER, 250, TimeUnit.MILLISECONDS); adapter.setSelectMode(false); setAdapterCurrentCoordinates(true); @@ -533,12 +544,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } private void setAdapterCurrentCoordinates(final boolean forceSort) { - final Geopoint coordsNow = app.currentGeo().getCoords(); - if (coordsNow != null) { - adapter.setActualCoordinates(coordsNow); - if (forceSort) { - adapter.forceSort(); - } + adapter.setActualCoordinates(Sensors.getInstance().currentGeo().getCoords()); + if (forceSort) { + adapter.forceSort(); } } @@ -552,8 +560,8 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.cache_list_options, menu); - CacheListAppFactory.addMenuItems(menu, this, res); sortProvider = (SortActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_sort)); + assert sortProvider != null; // We set it in the XML file sortProvider.setSelection(adapter.getCacheComparator()); sortProvider.setClickListener(new Action1<CacheComparator>() { @@ -572,6 +580,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA sortProvider.setSelection(selectedComparator); } }); + + ListNavigationSelectionActionProvider.initialize(menu.findItem(R.id.menu_cache_list_app_provider), new ListNavigationSelectionActionProvider.Callback() { + + @Override + public void onListNavigationSelected(final CacheListApp app) { + app.invoke(cacheList, CacheListActivity.this, getFilteredSearch()); + } + }); + return true; } @@ -632,6 +649,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA setMenuItemLabel(menu, R.id.menu_remove_from_history, R.string.cache_remove_from_history, R.string.cache_clear_history); menu.findItem(R.id.menu_import_android).setVisible(Compatibility.isStorageAccessFrameworkAvailable() && isOffline); + + final List<CacheListApp> listNavigationApps = CacheListApps.getActiveApps(); + menu.findItem(R.id.menu_cache_list_app_provider).setVisible(listNavigationApps.size() > 1); + menu.findItem(R.id.menu_cache_list_app).setVisible(listNavigationApps.size() == 1); + } catch (final RuntimeException e) { Log.e("CacheListActivity.onPrepareOptionsMenu", e); } @@ -641,7 +663,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA private boolean containsPastEvents() { for (final Geocache cache : adapter.getCheckedOrAllCaches()) { - if (DateUtils.isPastEvent(cache)) { + if (CalendarUtils.isPastEvent(cache)) { return true; } } @@ -672,9 +694,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA @Override public boolean onOptionsItemSelected(final MenuItem item) { - if (super.onOptionsItemSelected(item)) { - return true; - } switch (item.getItemId()) { case R.id.menu_show_on_map: goMap(); @@ -698,23 +717,23 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case R.id.menu_import_android: importGpxFromAndroid(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_create_list: - new StoredList.UserInterface(this).promptForListCreation(getListSwitchingRunnable(), newListName); + new StoredList.UserInterface(this).promptForListCreation(getListSwitchingRunnable(), listNameMemento.getTerm()); refreshSpinnerAdapter(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_drop_list: removeList(false); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_rename_list: renameList(); - return false; + return true; case R.id.menu_invert_selection: adapter.invertSelection(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_filter: showFilterMenu(null); return true; @@ -730,7 +749,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case R.id.menu_remove_from_history: removeFromHistoryCheck(); invalidateOptionsMenuCompatible(); - return false; + return true; case R.id.menu_move_to_list: moveCachesToOtherList(); invalidateOptionsMenuCompatible(); @@ -744,13 +763,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA invalidateOptionsMenuCompatible(); return true; case R.id.menu_cache_list_app: - if (!cacheToShow()) { - return false; + if (cacheToShow()) { + CacheListApps.getActiveApps().get(0).invoke(cacheList, this, getFilteredSearch()); } - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, getFilteredSearch()); - default: - return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search); + return true; } + return super.onOptionsItemSelected(item); } private boolean cacheToShow() { @@ -762,26 +780,28 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } private SearchResult getFilteredSearch() { - final Set<String> geocodes = new HashSet<>(); - for (final Geocache cache : adapter.getFilteredList()) { - geocodes.add(cache.getGeocode()); - } - return new SearchResult(geocodes); + return new SearchResult(Geocache.getGeocodes(adapter.getFilteredList())); } - public void deletePastEvents() { + private void deletePastEvents() { final List<Geocache> deletion = new ArrayList<>(); for (final Geocache cache : adapter.getCheckedOrAllCaches()) { - if (DateUtils.isPastEvent(cache)) { + if (CalendarUtils.isPastEvent(cache)) { deletion.add(cache); } } - new DropDetailsTask().execute(deletion.toArray(new Geocache[deletion.size()])); + new DropDetailsTask(0).execute(deletion.toArray(new Geocache[deletion.size()])); } - public void clearOfflineLogs() { - progress.show(this, null, res.getString(R.string.caches_clear_offlinelogs_progress), true, clearOfflineLogsHandler.cancelMessage()); - new ClearOfflineLogsThread(clearOfflineLogsHandler).start(); + private void clearOfflineLogs() { + Dialogs.confirmYesNo(this, R.string.caches_clear_offlinelogs, R.string.caches_clear_offlinelogs_message, new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + progress.show(CacheListActivity.this, null, res.getString(R.string.caches_clear_offlinelogs_progress), true, clearOfflineLogsHandler.cancelMessage()); + clearOfflineLogs(clearOfflineLogsHandler, adapter.getCheckedOrAllCaches()); + } + }); } /** @@ -789,12 +809,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA */ @Override public void showFilterMenu(final View view) { - new FilterUserInterface(this).selectFilter(new Action1<IFilter>() { - @Override - public void call(@Nullable final IFilter selectedFilter) { - setFilter(selectedFilter); - } - }); + FilterActivity.selectFilter(this); } private void setComparator(final CacheComparator comparator) { @@ -886,13 +901,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA CacheDetailActivity.startActivity(this, cache.getGeocode(), cache.getName()); break; case R.id.menu_drop_cache: + final int lastListPosition = getListView().getFirstVisiblePosition(); cache.drop(new Handler() { @Override public void handleMessage(final Message msg) { adapter.notifyDataSetChanged(); refreshCurrentList(); + getListView().setSelection(lastListPosition); } - }, Schedulers.io()); + }); break; case R.id.menu_move_to_list: new StoredList.UserInterface(this).promptForListSelection(R.string.cache_menu_move_list, new Action1<Integer>() { @@ -903,7 +920,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA adapter.setSelectMode(false); refreshCurrentList(); } - }, true, listId, newListName); + }, true, listId, listNameMemento); break; case R.id.menu_store_cache: case R.id.menu_refresh: @@ -1037,8 +1054,14 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA new GPXImporter(this, listId, importGpxAttachementFinishedHandler).importGPX(uri, null, getDisplayName(uri)); } } + else if (requestCode == FilterActivity.REQUEST_SELECT_FILTER && resultCode == Activity.RESULT_OK) { + final int[] filterIndex = data.getIntArrayExtra(FilterActivity.EXTRA_FILTER_RESULT); + setFilter(FilterActivity.getFilterFromPosition(filterIndex[0], filterIndex[1])); + } - refreshCurrentList(); + if (type == CacheListType.OFFLINE) { + refreshCurrentList(); + } } private String getDisplayName(final Uri uri) { @@ -1062,7 +1085,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return; } - if (!Network.isNetworkConnected(getApplicationContext())) { + if (!Network.isNetworkConnected()) { showToast(getString(R.string.err_server)); return; } @@ -1079,11 +1102,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } refreshStoredInternal(caches); } - }, true, StoredList.TEMPORARY_LIST_ID, newListName); + }, true, StoredList.TEMPORARY_LIST.id, listNameMemento); } else { if (type != CacheListType.OFFLINE) { for (final Geocache geocache : caches) { - if (geocache.getListId() == StoredList.TEMPORARY_LIST_ID) { + if (geocache.getListId() == StoredList.TEMPORARY_LIST.id) { geocache.setListId(StoredList.STANDARD_LIST_ID); } } @@ -1093,25 +1116,25 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } private void refreshStoredInternal(final List<Geocache> caches) { - detailProgress = 0; + detailProgress.set(0); showProgress(false); final int etaTime = ((detailTotal * 25) / 60); - String message; + final String message; if (etaTime < 1) { message = res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm); } else { message = res.getString(R.string.caches_downloading) + " " + res.getQuantityString(R.plurals.caches_eta_mins, etaTime, etaTime); } + final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler(); progress.show(this, null, message, ProgressDialog.STYLE_HORIZONTAL, loadDetailsHandler.cancelMessage()); progress.setMaxProgressAndReset(detailTotal); detailProgressTime = System.currentTimeMillis(); - final LoadDetailsThread threadDetails = new LoadDetailsThread(loadDetailsHandler, caches); - threadDetails.start(); + loadDetails(loadDetailsHandler, caches); } public void removeFromHistoryCheck() { @@ -1126,18 +1149,17 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA }); } - public void removeFromHistory() { + private void removeFromHistory() { final List<Geocache> caches = adapter.getCheckedOrAllCaches(); final String[] geocodes = new String[caches.size()]; for (int i = 0; i < geocodes.length; i++) { geocodes[i] = caches.get(i).getGeocode(); } - final Bundle b = new Bundle(); - b.putStringArray(Intents.EXTRA_CACHELIST, geocodes); - getSupportLoaderManager().initLoader(CacheListLoaderType.REMOVE_FROM_HISTORY.getLoaderId(), b, this); + DataStore.clearVisitDate(geocodes); + refreshCurrentList(); } - public void importWeb() { + private void importWeb() { // menu is also shown with no device connected if (!Settings.isRegisteredForSend2cgeo()) { Dialogs.confirm(this, R.string.web_import_title, R.string.init_sendToCgeo_description, new OnClickListener() { @@ -1150,146 +1172,92 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return; } - detailProgress = 0; + detailProgress.set(0); showProgress(false); final DownloadFromWebHandler downloadFromWebHandler = new DownloadFromWebHandler(); progress.show(this, null, res.getString(R.string.web_import_waiting), true, downloadFromWebHandler.cancelMessage()); - - final LoadFromWebThread threadWeb = new LoadFromWebThread(downloadFromWebHandler, listId); - threadWeb.start(); + Send2CgeoDownloader.loadFromWeb(downloadFromWebHandler, listId); } - public void dropStored() { + private void dropStored() { final int titleId = (adapter.getCheckedCount() > 0) ? R.string.caches_remove_selected : R.string.caches_remove_all; - final int messageId = (adapter.getCheckedCount() > 0) ? R.string.caches_remove_selected_confirm : R.string.caches_remove_all_confirm; - final String message = getString(messageId, adapter.getCheckedOrAllCount()); + final int count = adapter.getCheckedOrAllCount(); + final String message = res.getQuantityString(adapter.getCheckedCount() > 0 ? R.plurals.caches_remove_selected_confirm : R.plurals.caches_remove_all_confirm, count, count); Dialogs.confirmYesNo(this, titleId, message, new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int id) { final List<Geocache> selected = adapter.getCheckedOrAllCaches(); - new DropDetailsTask().execute(selected.toArray(new Geocache[selected.size()])); + final int lastListPosition = getListView().getFirstVisiblePosition(); + new DropDetailsTask(lastListPosition).execute(selected.toArray(new Geocache[selected.size()])); dialog.cancel(); } }); } /** - * Thread to refresh the cache details. + * Method to asynchronously refresh the caches details. */ - private class LoadDetailsThread extends Thread { - - final private CancellableHandler handler; - final private List<Geocache> caches; - - public LoadDetailsThread(final CancellableHandler handler, final List<Geocache> caches) { - this.handler = handler; - this.caches = caches; - } - - @Override - public void run() { - // First refresh caches that do not yet have static maps to get them a chance to get a copy - // before the limit expires, unless we do not want to store offline maps. - final List<Geocache> allCaches = Settings.isStoreOfflineMaps() ? - ListUtils.union(ListUtils.selectRejected(caches, Geocache.hasStaticMap), - ListUtils.select(caches, Geocache.hasStaticMap)) : - caches; - - for (final Geocache cache : allCaches) { - if (!refreshCache(cache)) { - break; - } - } - - handler.sendEmptyMessage(MSG_DONE); - } - - /** - * Refreshes the cache information. - * - * @param cache - * The cache to refresh - * @return - * <code>false</code> if the storing was interrupted, <code>true</code> otherwise - */ - private boolean refreshCache(final Geocache cache) { - try { - if (handler.isCancelled()) { - throw new InterruptedException("Stopped storing process."); - } - detailProgress++; - cache.refreshSynchronous(null); - handler.sendEmptyMessage(cacheList.indexOf(cache)); - } catch (final InterruptedException e) { - Log.i(e.getMessage()); - return false; - } catch (final Exception e) { - Log.e("CacheListActivity.LoadDetailsThread", e); - } - - return true; - } - } - - private static class LoadFromWebThread extends Thread { - - final private CancellableHandler handler; - final private int listIdLFW; - - public LoadFromWebThread(final CancellableHandler handler, final int listId) { - this.handler = handler; - listIdLFW = StoredList.getConcreteList(listId); - } - - @Override - public void run() { - long baseTime = System.currentTimeMillis(); - - final String deviceCode = StringUtils.defaultString(Settings.getWebDeviceCode()); - final Parameters params = new Parameters("code", deviceCode); - while (!handler.isCancelled() && System.currentTimeMillis() - baseTime < 3 * 60000) { // maximum: 3 minutes - // Download new code - final HttpResponse responseFromWeb = Network.getRequest("http://send2.cgeo.org/read.html", params); - - if (responseFromWeb != null && responseFromWeb.getStatusLine().getStatusCode() == 200) { - final String response = Network.getResponseData(responseFromWeb); - if (response != null && response.length() > 2) { - handler.sendMessage(handler.obtainMessage(MSG_LOADING, response)); - - Geocache.storeCache(null, response, listIdLFW, false, null); - - handler.sendMessage(handler.obtainMessage(MSG_LOADED, response)); - baseTime = System.currentTimeMillis(); - } else if ("RG".equals(response)) { - //Server returned RG (registration) and this device no longer registered. - Settings.setWebNameCode(null, null); - handler.sendEmptyMessage(MSG_NO_REGISTRATION); - handler.cancel(); - break; - } else { - try { - sleep(5000); // Wait for 5s if no cache found - } catch (final InterruptedException e) { + private void loadDetails(final CancellableHandler handler, final List<Geocache> caches) { + final Observable<Geocache> allCaches; + final Subscription generator; + if (Settings.isStoreOfflineMaps()) { + // The list of caches will be generated in the background, putting the caches without static maps first. + final ReplaySubject<Geocache> withStaticMaps = ReplaySubject.create(caches.size()); + final ReplaySubject<Geocache> withoutStaticMaps = ReplaySubject.create(caches.size()); + final Worker worker = Schedulers.io().createWorker(); + generator = worker.schedule(new Action0() { + @Override + public void call() { + for (final Geocache cache : caches) { + if (worker.isUnsubscribed()) { + // Do not continue to check for static maps if the user pressed cancel. + return; + } + if (cache.hasStaticMap()) { + withStaticMaps.onNext(cache); + } else { + withoutStaticMaps.onNext(cache); } - handler.sendEmptyMessage(MSG_WAITING); } - } else { - handler.sendEmptyMessage(MSG_SERVER_FAIL); - handler.cancel(); - break; + withStaticMaps.onCompleted(); + withoutStaticMaps.onCompleted(); } - } - - handler.sendEmptyMessage(MSG_DONE); + }); + allCaches = Observable.concat(withoutStaticMaps, withStaticMaps); + } else { + allCaches = Observable.from(caches); + generator = Subscriptions.empty(); } + final Observable<Geocache> loaded = allCaches.flatMap(new Func1<Geocache, Observable<Geocache>>() { + @Override + public Observable<Geocache> call(final Geocache cache) { + return Observable.create(new OnSubscribe<Geocache>() { + @Override + public void call(final Subscriber<? super Geocache> subscriber) { + cache.refreshSynchronous(null); + detailProgress.incrementAndGet(); + handler.obtainMessage(DownloadProgress.MSG_LOADED, cache).sendToTarget(); + subscriber.onCompleted(); + } + }).subscribeOn(RxUtils.refreshScheduler); + } + }).doOnCompleted(new Action0() { + @Override + public void call() { + handler.sendEmptyMessage(DownloadProgress.MSG_DONE); + } + }); + handler.unsubscribeIfCancelled(new CompositeSubscription(generator, loaded.subscribe())); } private class DropDetailsTask extends AsyncTaskWithProgress<Geocache, Void> { + private final int lastListPosition; - public DropDetailsTask() { + public DropDetailsTask(final int lastListPosition) { super(CacheListActivity.this, null, res.getString(R.string.caches_remove_progress), true); + this.lastListPosition = lastListPosition; } @Override @@ -1303,25 +1271,19 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA adapter.setSelectMode(false); refreshCurrentList(); replaceCacheListFromSearch(); + getListView().setSelection(lastListPosition); } } - private class ClearOfflineLogsThread extends Thread { - - final private Handler handler; - final private List<Geocache> selected; - - public ClearOfflineLogsThread(final Handler handlerIn) { - handler = handlerIn; - selected = adapter.getCheckedOrAllCaches(); - } - - @Override - public void run() { - DataStore.clearLogsOffline(selected); - handler.sendEmptyMessage(MSG_DONE); - } + private static void clearOfflineLogs(final Handler handler, final List<Geocache> selectedCaches) { + Schedulers.io().createWorker().schedule(new Action0() { + @Override + public void call() { + DataStore.clearLogsOffline(selectedCaches); + handler.sendEmptyMessage(DownloadProgress.MSG_DONE); + } + }); } private class MoreCachesListener implements View.OnClickListener { @@ -1355,13 +1317,13 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA }; } - public void switchListById(final int id) { + private void switchListById(final int id) { if (id < 0) { return; } if (id == PseudoList.HISTORY_LIST.id) { - CacheListActivity.startActivityHistory(this); + startActivity(CacheListActivity.getHistoryIntent(this)); finish(); return; } @@ -1371,9 +1333,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA title = res.getString(R.string.list_all_lists); } else { final StoredList list = DataStore.getList(id); - if (list == null) { - return; - } listId = list.id; title = list.title; } @@ -1437,12 +1396,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA // apply filter settings (if there's a filter) final SearchResult searchToUse = getFilteredSearch(); - final int count = searchToUse.getCount(); - String mapTitle = title; - if (count > 0) { - mapTitle = title + " [" + count + "]"; - } - CGeoMap.startActivitySearch(this, searchToUse, mapTitle); + CGeoMap.startActivitySearch(this, searchToUse, title); } private void refreshCurrentList() { @@ -1452,7 +1406,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA public static void startActivityOffline(final Context context) { final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.OFFLINE); + Intents.putListType(cachesIntent, CacheListType.OFFLINE); context.startActivity(cachesIntent); } @@ -1461,7 +1415,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return; } final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.OWNER); + Intents.putListType(cachesIntent, CacheListType.OWNER); cachesIntent.putExtra(Intents.EXTRA_USERNAME, userName); context.startActivity(cachesIntent); } @@ -1479,7 +1433,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return; } final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.FINDER); + Intents.putListType(cachesIntent, CacheListType.FINDER); cachesIntent.putExtra(Intents.EXTRA_USERNAME, userName); context.startActivity(cachesIntent); } @@ -1500,37 +1454,39 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } } - public static void startActivityNearest(final AbstractActivity context, final Geopoint coordsNow) { - if (!isValidCoords(context, coordsNow)) { - return; - } - final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.NEAREST); - cachesIntent.putExtra(Intents.EXTRA_COORDS, coordsNow); - context.startActivity(cachesIntent); + public static Intent getNearestIntent(final Activity context) { + return Intents.putListType(new Intent(context, CacheListActivity.class), CacheListType.NEAREST); } - public static void startActivityHistory(final Context context) { - final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.HISTORY); - context.startActivity(cachesIntent); + public static Intent getHistoryIntent(final Context context) { + return Intents.putListType(new Intent(context, CacheListActivity.class), CacheListType.HISTORY); } public static void startActivityAddress(final Context context, final Geopoint coords, final String address) { final Intent addressIntent = new Intent(context, CacheListActivity.class); - addressIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.ADDRESS); + Intents.putListType(addressIntent, CacheListType.ADDRESS); addressIntent.putExtra(Intents.EXTRA_COORDS, coords); addressIntent.putExtra(Intents.EXTRA_ADDRESS, address); context.startActivity(addressIntent); } - public static void startActivityCoordinates(final AbstractActivity context, final Geopoint coords) { + /** + * start list activity, by searching around the given point. + * + * @param name + * name of coordinates, will lead to a title like "Around ..." instead of directly showing the + * coordinates as title + */ + public static void startActivityCoordinates(final AbstractActivity context, final Geopoint coords, @Nullable final String name) { if (!isValidCoords(context, coords)) { return; } final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.COORDINATE); + Intents.putListType(cachesIntent, CacheListType.COORDINATE); cachesIntent.putExtra(Intents.EXTRA_COORDS, coords); + if (StringUtils.isNotEmpty(name)) { + cachesIntent.putExtra(Intents.EXTRA_TITLE, context.getString(R.string.around, name)); + } context.startActivity(cachesIntent); } @@ -1548,15 +1504,15 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return; } final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.KEYWORD); + Intents.putListType(cachesIntent, CacheListType.KEYWORD); cachesIntent.putExtra(Intents.EXTRA_KEYWORD, keyword); context.startActivity(cachesIntent); } public static void startActivityMap(final Context context, final SearchResult search) { final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.MAP); cachesIntent.putExtra(Intents.EXTRA_SEARCH, search); + Intents.putListType(cachesIntent, CacheListType.MAP); context.startActivity(cachesIntent); } @@ -1567,7 +1523,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return; } final Intent cachesIntent = new Intent(context, CacheListActivity.class); - cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.POCKET); + Intents.putListType(cachesIntent, CacheListType.POCKET); cachesIntent.putExtra(Intents.EXTRA_NAME, pq.getName()); cachesIntent.putExtra(Intents.EXTRA_POCKET_GUID, guid); context.startActivity(cachesIntent); @@ -1592,7 +1548,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } if (listId == PseudoList.ALL_LIST.id) { title = res.getString(R.string.list_all_lists); - } else if (listId <= StoredList.TEMPORARY_LIST_ID) { + } else if (listId <= StoredList.TEMPORARY_LIST.id) { listId = StoredList.STANDARD_LIST_ID; title = res.getString(R.string.stored_caches_button); } else { @@ -1605,7 +1561,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA title = list.title; } - loader = new OfflineGeocacheListLoader(this.getBaseContext(), coords, listId); + loader = new OfflineGeocacheListLoader(getBaseContext(), coords, listId); break; case HISTORY: @@ -1623,31 +1579,26 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA break; case KEYWORD: final String keyword = extras.getString(Intents.EXTRA_KEYWORD); - rememberTerm(keyword); + title = listNameMemento.rememberTerm(keyword); loader = new KeywordGeocacheListLoader(app, keyword); break; case ADDRESS: final String address = extras.getString(Intents.EXTRA_ADDRESS); if (StringUtils.isNotBlank(address)) { - rememberTerm(address); + title = listNameMemento.rememberTerm(address); } else { title = coords.toString(); } - if (coords != null) { - loader = new CoordsGeocacheListLoader(app, coords); - } - else { - loader = new AddressGeocacheListLoader(app, address); - } + loader = new CoordsGeocacheListLoader(app, coords); break; case FINDER: final String username = extras.getString(Intents.EXTRA_USERNAME); - rememberTerm(username); + title = listNameMemento.rememberTerm(username); loader = new FinderGeocacheListLoader(app, username); break; case OWNER: final String ownerName = extras.getString(Intents.EXTRA_USERNAME); - rememberTerm(ownerName); + title = listNameMemento.rememberTerm(ownerName); loader = new OwnerGeocacheListLoader(app, ownerName); break; case MAP: @@ -1657,10 +1608,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA replaceCacheListFromSearch(); loadCachesHandler.sendMessage(Message.obtain()); break; - case REMOVE_FROM_HISTORY: - title = res.getString(R.string.caches_history); - loader = new RemoveFromHistoryLoader(app, extras.getStringArray(Intents.EXTRA_CACHELIST), coords); - break; case NEXT_PAGE: loader = new NextPageGeocacheListLoader(app, search); break; @@ -1670,6 +1617,10 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA loader = new PocketGeocacheListLoader(app, guid); break; } + // if there is a title given in the activity start request, use this one instead of the default + if (extras != null && StringUtils.isNotBlank(extras.getString(Intents.EXTRA_TITLE))) { + title = extras.getString(Intents.EXTRA_TITLE); + } updateTitle(); showProgress(true); showFooterLoadingCaches(); @@ -1680,13 +1631,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return loader; } - private void rememberTerm(final String term) { - // set the title of the activity - title = term; - // and remember this term for potential use in list creation - newListName = term; - } - @Override public void onLoadFinished(final Loader<SearchResult> arg0, final SearchResult searchIn) { // The database search was moved into the UI call intentionally. If this is done before the runOnUIThread, @@ -1716,8 +1660,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA /** * Allow the title bar spinner to show the same subtitle like the activity itself would show. * - * @param list - * @return */ public CharSequence getCacheListSubtitle(@NonNull final AbstractList list) { // if this is the current list, be aware of filtering @@ -1735,7 +1677,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA /** * Calculate the subtitle of the current list depending on (optional) filters. * - * @return */ private CharSequence getCurrentSubtitle() { final ArrayList<String> numbers = new ArrayList<>(); diff --git a/main/src/cgeo/geocaching/CacheMenuHandler.java b/main/src/cgeo/geocaching/CacheMenuHandler.java index 0dc6444..fbd8771 100644 --- a/main/src/cgeo/geocaching/CacheMenuHandler.java +++ b/main/src/cgeo/geocaching/CacheMenuHandler.java @@ -3,8 +3,11 @@ package cgeo.geocaching; import cgeo.calendar.CalendarAddon; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cache.navi.NavigationSelectionActionProvider; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractUIFactory; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; @@ -18,7 +21,11 @@ import android.view.MenuItem; * TODO: replace by a fragment * */ -public class CacheMenuHandler extends AbstractUIFactory { +public final class CacheMenuHandler extends AbstractUIFactory { + + private CacheMenuHandler() { + // utility class + } /** * Methods to be implemented by the activity to react to the cache menu selections. @@ -33,7 +40,7 @@ public class CacheMenuHandler extends AbstractUIFactory { } - public static boolean onMenuItemSelected(final MenuItem item, final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) { + public static boolean onMenuItemSelected(final MenuItem item, @NonNull final CacheMenuHandler.ActivityInterface activityInterface, final Geocache cache) { assert activityInterface instanceof Activity || activityInterface instanceof Fragment; final Activity activity; if (activityInterface instanceof Activity) { @@ -85,7 +92,8 @@ public class CacheMenuHandler extends AbstractUIFactory { menu.findItem(R.id.menu_navigate).setVisible(hasCoords); menu.findItem(R.id.menu_caches_around).setVisible(hasCoords && cache.supportsCachesAround()); menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar()); - menu.findItem(R.id.menu_show_in_browser).setVisible(cache.canOpenInBrowser()); + menu.findItem(R.id.menu_log_visit).setVisible(cache.supportsLogging() && !Settings.getLogOffline()); + menu.findItem(R.id.menu_log_visit_offline).setVisible(cache.supportsLogging() && Settings.getLogOffline()); menu.findItem(R.id.menu_default_navigation).setTitle(NavigationAppFactory.getDefaultNavigationApplication().getName()); diff --git a/main/src/cgeo/geocaching/CachePopupFragment.java b/main/src/cgeo/geocaching/CachePopupFragment.java index b2af12c..ff4348a 100644 --- a/main/src/cgeo/geocaching/CachePopupFragment.java +++ b/main/src/cgeo/geocaching/CachePopupFragment.java @@ -2,8 +2,8 @@ package cgeo.geocaching; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.network.Network; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.CacheDetailsCreator; @@ -17,13 +17,12 @@ import rx.functions.Action0; import rx.functions.Action1; import rx.schedulers.Schedulers; -import android.content.Context; -import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -135,20 +134,25 @@ public class CachePopupFragment extends AbstractDialogFragment { public void call(final Integer selectedListId) { storeCache(selectedListId); } - }, true, StoredList.TEMPORARY_LIST_ID); + }, true, StoredList.TEMPORARY_LIST.id); } else { - storeCache(StoredList.TEMPORARY_LIST_ID); + storeCache(StoredList.TEMPORARY_LIST.id); } } protected void storeCache(final int listId) { final StoreCacheHandler storeCacheHandler = new StoreCacheHandler(R.string.cache_dialog_offline_save_message); - progress.show(getActivity(), res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage()); - Schedulers.io().createWorker().schedule(new Action0() { + final FragmentActivity activity = getActivity(); + progress.show(activity, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage()); + RxUtils.andThenOnUi(Schedulers.io(), new Action0() { @Override public void call() { cache.store(listId, storeCacheHandler); - getActivity().supportInvalidateOptionsMenu(); + } + }, new Action0() { + @Override + public void call() { + activity.supportInvalidateOptionsMenu(); } }); } @@ -162,7 +166,7 @@ public class CachePopupFragment extends AbstractDialogFragment { return; } - if (!Network.isNetworkConnected(getActivity())) { + if (!Network.isNetworkConnected()) { showToast(getString(R.string.err_server)); return; } @@ -183,7 +187,7 @@ public class CachePopupFragment extends AbstractDialogFragment { final DropCacheHandler dropCacheHandler = new DropCacheHandler(); progress.show(getActivity(), res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null); - cache.drop(dropCacheHandler, Schedulers.io()); + cache.drop(dropCacheHandler); } } @@ -212,12 +216,6 @@ public class CachePopupFragment extends AbstractDialogFragment { getActivity().finish(); } - public static void startActivity(final Context context, final String geocode) { - final Intent popupIntent = new Intent(context, CachePopup.class); - popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode); - context.startActivity(popupIntent); - } - @Override protected Geopoint getCoordinates() { if (cache == null) { diff --git a/main/src/cgeo/geocaching/CgeoApplication.java b/main/src/cgeo/geocaching/CgeoApplication.java index a81319d..d74acea 100644 --- a/main/src/cgeo/geocaching/CgeoApplication.java +++ b/main/src/cgeo/geocaching/CgeoApplication.java @@ -1,15 +1,15 @@ package cgeo.geocaching; -import cgeo.geocaching.sensors.DirectionProvider; -import cgeo.geocaching.sensors.GeoDataProvider; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.OOMDumpingUncaughtExceptionHandler; +import cgeo.geocaching.utils.RxUtils; -import rx.Observable; -import rx.functions.Action1; -import rx.observables.ConnectableObservable; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesUtil; + +import org.eclipse.jdt.annotation.NonNull; import android.app.Application; import android.view.ViewConfiguration; @@ -22,10 +22,7 @@ public class CgeoApplication extends Application { public boolean showLoginToast = true; //login toast shown just once. private boolean liveMapHintShownInThisSession = false; // livemap hint has been shown private static CgeoApplication instance; - private Observable<IGeoData> geoDataObservable; - private Observable<Float> directionObservable; - private volatile IGeoData currentGeo = null; - private volatile float currentDirection = 0.0f; + private boolean isGooglePlayServicesAvailable = false; public static void dumpOnOutOfMemory(final boolean enable) { @@ -45,7 +42,7 @@ public class CgeoApplication extends Application { setInstance(this); } - private static void setInstance(final CgeoApplication application) { + private static void setInstance(@NonNull final CgeoApplication application) { instance = application; } @@ -60,12 +57,7 @@ public class CgeoApplication extends Application { final Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); - } catch (final IllegalArgumentException e) { - // ignore - } catch (final NoSuchFieldException e) { - // ignore - } catch (final IllegalAccessException e) { - // ignore + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException ignored) { } // Set language to English if the user decided so. @@ -73,55 +65,32 @@ public class CgeoApplication extends Application { // ensure initialization of lists DataStore.getLists(); - } - - @Override - public void onLowMemory() { - Log.i("Cleaning applications cache."); - DataStore.removeAllFromCache(); - } - public synchronized Observable<IGeoData> geoDataObservable() { - if (geoDataObservable == null) { - final ConnectableObservable<IGeoData> onDemand = GeoDataProvider.create(this).replay(1); - onDemand.subscribe(new Action1<IGeoData>() { - @Override - public void call(final IGeoData geoData) { - currentGeo = geoData; - } - }); - geoDataObservable = onDemand.refCount(); + // Check if Google Play services is available + if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) { + isGooglePlayServicesAvailable = true; } - return geoDataObservable; - } + Log.i("Google Play services are " + (isGooglePlayServicesAvailable ? "" : "not ") + "available"); + final Sensors sensors = Sensors.getInstance(); + sensors.setupGeoDataObservables(Settings.useGooglePlayServices(), Settings.useLowPowerMode()); + sensors.setupDirectionObservable(Settings.useLowPowerMode()); - public synchronized Observable<Float> directionObservable() { - if (directionObservable == null) { - final ConnectableObservable<Float> onDemand = DirectionProvider.create(this).replay(1); - onDemand.subscribe(new Action1<Float>() { - @Override - public void call(final Float direction) { - currentDirection = direction; - } - }); - directionObservable = onDemand.refCount(); - } - return directionObservable; + // Attempt to acquire an initial location before any real activity happens. + sensors.geoDataObservable(true).subscribeOn(RxUtils.looperCallbacksScheduler).first().subscribe(); } - public IGeoData currentGeo() { - return currentGeo != null ? currentGeo : geoDataObservable().toBlocking().first(); - } - public Float distanceNonBlocking(final ICoordinates target) { - if (currentGeo == null || target.getCoords() == null) { - return null; - } - return currentGeo.getCoords().distanceTo(target); + @Override + public void onLowMemory() { + onTrimMemory(TRIM_MEMORY_COMPLETE); } - public float currentDirection() { - return currentDirection; + @Override + public void onTrimMemory(final int level) { + if (level >= TRIM_MEMORY_MODERATE) { + Log.i("Cleaning applications cache to trim memory"); + DataStore.removeAllFromCache(); + } } public boolean isLiveMapHintShownInThisSession() { @@ -150,4 +119,8 @@ public class CgeoApplication extends Application { forceRelog = true; } + public boolean isGooglePlayServicesAvailable() { + return isGooglePlayServicesAvailable; + } + } diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java index 025d938..3f6fe6a 100644 --- a/main/src/cgeo/geocaching/CompassActivity.java +++ b/main/src/cgeo/geocaching/CompassActivity.java @@ -4,28 +4,35 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActionBarActivity; +import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; import cgeo.geocaching.maps.CGeoMap; -import cgeo.geocaching.sensors.DirectionProvider; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.speech.SpeechService; import cgeo.geocaching.ui.CompassView; import cgeo.geocaching.ui.LoggingUI; +import cgeo.geocaching.utils.AngleUtils; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; +import com.github.amlcurran.showcaseview.targets.ActionItemTarget; + import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; + import android.content.Context; import android.content.Intent; import android.content.res.Configuration; -import android.hardware.Sensor; -import android.hardware.SensorManager; import android.media.AudioManager; import android.os.Bundle; import android.view.Menu; @@ -34,14 +41,10 @@ import android.view.SubMenu; import android.view.View; import android.widget.TextView; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; public class CompassActivity extends AbstractActionBarActivity { - private static final int COORDINATES_OFFSET = 10; - @InjectView(R.id.nav_type) protected TextView navType; @InjectView(R.id.nav_accuracy) protected TextView navAccuracy; @InjectView(R.id.nav_satellites) protected TextView navSatellites; @@ -52,73 +55,70 @@ public class CompassActivity extends AbstractActionBarActivity { @InjectView(R.id.destination) protected TextView destinationTextView; @InjectView(R.id.cacheinfo) protected TextView cacheInfoView; - private static final String EXTRAS_COORDS = "coords"; - private static final String EXTRAS_NAME = "name"; - private static final String EXTRAS_GEOCODE = "geocode"; - private static final String EXTRAS_CACHE_INFO = "cacheinfo"; - private static final List<IWaypoint> coordinates = new ArrayList<>(); - /** - * Destination of the compass, or null (if the compass is used for a waypoint only). + * Destination cache, may be null + */ + private Geocache cache = null; + /** + * Destination waypoint, may be null */ - private @Nullable Geocache cache = null; + private Waypoint waypoint = null; private Geopoint dstCoords = null; private float cacheHeading = 0; - private String title = null; - private String info = null; - private boolean hasMagneticFieldSensor; + private String description; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.compass_activity); - - final SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); - hasMagneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null; - if (!hasMagneticFieldSensor) { - Settings.setUseCompass(false); - } + ButterKnife.inject(this); // get parameters final Bundle extras = getIntent().getExtras(); - if (extras != null) { - final String geocode = extras.getString(EXTRAS_GEOCODE); - if (StringUtils.isNotEmpty(geocode)) { - cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); - } - title = geocode; - final String name = extras.getString(EXTRAS_NAME); - dstCoords = extras.getParcelable(EXTRAS_COORDS); - info = extras.getString(EXTRAS_CACHE_INFO); - - if (StringUtils.isNotBlank(name)) { - if (StringUtils.isNotBlank(title)) { - title += ": " + name; - } else { - title = name; - } - } - } else { - final Intent pointIntent = new Intent(this, NavigateAnyPointActivity.class); - startActivity(pointIntent); - + if (extras == null) { finish(); return; } - // set header - setTitle(); - setDestCoords(); - setCacheInfo(); + // cache must exist, except for "any point navigation" + final String geocode = extras.getString(Intents.EXTRA_GEOCODE); + if (geocode != null) { + cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + } - ButterKnife.inject(this); + // find the wanted navigation target + if (extras.containsKey(Intents.EXTRA_WAYPOINT_ID)) { + final int waypointId = extras.getInt(Intents.EXTRA_WAYPOINT_ID); + final Waypoint waypoint = DataStore.loadWaypoint(waypointId); + if (waypoint != null) { + setTarget(waypoint); + } + } + else if (extras.containsKey(Intents.EXTRA_COORDS)) { + setTarget(extras.<Geopoint>getParcelable(Intents.EXTRA_COORDS), extras.getString(Intents.EXTRA_DESCRIPTION)); + } + else { + setTarget(cache); + } + + // set activity title just once, independent of what target is switched to + if (cache != null) { + setCacheTitleBar(cache); + } + else { + setTitle(StringUtils.defaultIfBlank(extras.getString(Intents.EXTRA_NAME), res.getString(R.string.navigation))); + } // make sure we can control the TTS volume setVolumeControlStream(AudioManager.STREAM_MUSIC); + + presentShowcase(); } @Override public void onResume() { - super.onResume(geoDirHandler.start(GeoDirHandler.UPDATE_GEODIR)); + super.onResume(geoDirHandler.start(GeoDirHandler.UPDATE_GEODIR), + Sensors.getInstance().gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(gpsStatusHandler)); + forceRefresh(); } @Override @@ -134,38 +134,43 @@ public class CompassActivity extends AbstractActionBarActivity { setContentView(R.layout.compass_activity); ButterKnife.inject(this); + setTarget(dstCoords, description); - setTitle(); - setDestCoords(); - setCacheInfo(); + forceRefresh(); + } + private void forceRefresh() { // Force a refresh of location and direction when data is available. - final CgeoApplication app = CgeoApplication.getInstance(); - final IGeoData geo = app.currentGeo(); - if (geo != null) { - geoDirHandler.updateGeoDir(geo, app.currentDirection()); - } + final Sensors sensors = Sensors.getInstance(); + geoDirHandler.updateGeoDir(sensors.currentGeo(), sensors.currentDirection()); } @Override public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.compass_activity_options, menu); - menu.findItem(R.id.menu_compass_sensor).setVisible(hasMagneticFieldSensor); - final SubMenu subMenu = menu.findItem(R.id.menu_select_destination).getSubMenu(); - if (coordinates.size() > 1) { - for (int i = 0; i < coordinates.size(); i++) { - final IWaypoint coordinate = coordinates.get(i); - subMenu.add(0, COORDINATES_OFFSET + i, 0, coordinate.getName() + " (" + coordinate.getCoordType() + ")"); - } - } else { - menu.findItem(R.id.menu_select_destination).setVisible(false); - } + menu.findItem(R.id.menu_compass_sensor).setVisible(Sensors.getInstance().hasCompassCapabilities()); if (cache != null) { LoggingUI.addMenuItems(this, menu, cache); } + addWaypointItems(menu); return true; } + private void addWaypointItems(final Menu menu) { + if (cache != null) { + final List<Waypoint> waypoints = cache.getWaypoints(); + boolean visible = false; + final SubMenu subMenu = menu.findItem(R.id.menu_select_destination).getSubMenu(); + for (final Waypoint waypoint : waypoints) { + if (waypoint.getCoords() != null) { + subMenu.add(0, waypoint.getId(), 0, waypoint.getName()); + visible = true; + } + } + menu.findItem(R.id.menu_select_destination).setVisible(visible); + } + } + @Override public boolean onPrepareOptionsMenu(final Menu menu) { super.onPrepareOptionsMenu(menu); @@ -177,6 +182,8 @@ public class CompassActivity extends AbstractActionBarActivity { } menu.findItem(R.id.menu_tts_start).setVisible(!SpeechService.isRunning()); menu.findItem(R.id.menu_tts_stop).setVisible(SpeechService.isRunning()); + menu.findItem(R.id.menu_compass_cache).setVisible(cache != null); + menu.findItem(R.id.menu_hint).setVisible(cache != null); return true; } @@ -185,7 +192,15 @@ public class CompassActivity extends AbstractActionBarActivity { final int id = item.getItemId(); switch (id) { case R.id.menu_map: - CGeoMap.startActivityCoords(this, dstCoords, null, null); + if (waypoint != null) { + CGeoMap.startActivityCoords(this, waypoint.getCoords(), waypoint.getWaypointType(), waypoint.getName()); + } + else if (cache != null) { + CGeoMap.startActivityGeoCode(this, cache.getGeocode()); + } + else { + CGeoMap.startActivityCoords(this, dstCoords, null, null); + } return true; case R.id.menu_compass_sensor_gps: Settings.setUseCompass(false); @@ -203,36 +218,53 @@ public class CompassActivity extends AbstractActionBarActivity { SpeechService.stopService(this); invalidateOptionsMenuCompatible(); return true; + case R.id.menu_compass_cache: + setTarget(cache); + return true; + case R.id.menu_hint: + cache.showHintToast(this); + return true; default: if (LoggingUI.onMenuItemSelected(item, this, cache)) { return true; } - final int coordinatesIndex = id - COORDINATES_OFFSET; - if (coordinatesIndex >= 0 && coordinatesIndex < coordinates.size()) { - final IWaypoint coordinate = coordinates.get(coordinatesIndex); - title = coordinate.getName(); - dstCoords = coordinate.getCoords(); - setTitle(); - setDestCoords(); - setCacheInfo(); - updateDistanceInfo(app.currentGeo()); - - Log.d("destination set: " + title + " (" + dstCoords + ")"); - return true; + if (cache != null) { + final Waypoint waypoint = cache.getWaypointById(id); + if (waypoint != null) { + setTarget(waypoint); + return true; + } } } return super.onOptionsItemSelected(item); } - private void setTitle() { - if (StringUtils.isNotBlank(title)) { - setTitle(title); - } else { - setTitle(res.getString(R.string.navigation)); - } + @Override + public ShowcaseViewBuilder getShowcase() { + return new ShowcaseViewBuilder(this) + .setTarget(new ActionItemTarget(this, R.id.menu_hint)) + .setContent(R.string.showcase_compass_hint_title, R.string.showcase_compass_hint_text); } - private void setDestCoords() { + private void setTarget(@NonNull final Geopoint coords, final String newDescription) { + setDestCoords(coords); + setTargetDescription(newDescription); + updateDistanceInfo(Sensors.getInstance().currentGeo()); + + Log.d("destination set: " + newDescription + " (" + dstCoords + ")"); + } + + private void setTarget(final @NonNull Waypoint waypointIn) { + waypoint = waypointIn; + setTarget(waypointIn.getCoords(), waypointIn.getName()); + } + + private void setTarget(final Geocache cache) { + setTarget(cache.getCoords(), Formatter.formatCacheInfoShort(cache)); + } + + private void setDestCoords(final Geopoint coords) { + dstCoords = coords; if (dstCoords == null) { return; } @@ -240,17 +272,18 @@ public class CompassActivity extends AbstractActionBarActivity { destinationTextView.setText(dstCoords.toString()); } - private void setCacheInfo() { - if (info == null) { + private void setTargetDescription(final @Nullable String newDescription) { + description = newDescription; + if (this.description == null) { cacheInfoView.setVisibility(View.GONE); return; } cacheInfoView.setVisibility(View.VISIBLE); - cacheInfoView.setText(info); + cacheInfoView.setText(this.description); } - private void updateDistanceInfo(final IGeoData geo) { - if (geo.getCoords() == null || dstCoords == null) { + private void updateDistanceInfo(final GeoData geo) { + if (dstCoords == null) { return; } @@ -259,36 +292,36 @@ public class CompassActivity extends AbstractActionBarActivity { headingView.setText(Math.round(cacheHeading) + "°"); } + private final Action1<Status> gpsStatusHandler = new Action1<Status>() { + @Override + public void call(final Status gpsStatus) { + if (gpsStatus.satellitesVisible >= 0) { + navSatellites.setText(res.getString(R.string.loc_sat) + ": " + gpsStatus.satellitesFixed + "/" + gpsStatus.satellitesVisible); + } else { + navSatellites.setText(""); + } + } + }; + private final GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override - public void updateGeoDir(final IGeoData geo, final float dir) { + public void updateGeoDir(final GeoData geo, final float dir) { try { - if (geo.getCoords() != null) { - if (geo.getSatellitesVisible() >= 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": " + geo.getSatellitesFixed() + "/" + geo.getSatellitesVisible()); - } else { - navSatellites.setText(""); - } - navType.setText(res.getString(geo.getLocationProvider().resourceId)); + navType.setText(res.getString(geo.getLocationProvider().resourceId)); - if (geo.getAccuracy() >= 0) { - navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy())); - } else { - navAccuracy.setText(null); - } - - navLocation.setText(geo.getCoords().toString()); - - updateDistanceInfo(geo); + if (geo.getAccuracy() >= 0) { + navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy())); } else { - navType.setText(null); navAccuracy.setText(null); - navLocation.setText(res.getString(R.string.loc_trying)); } - updateNorthHeading(DirectionProvider.getDirectionNow(dir)); + navLocation.setText(geo.getCoords().toString()); + + updateDistanceInfo(geo); + + updateNorthHeading(AngleUtils.getDirectionNow(dir)); } catch (final RuntimeException e) { - Log.w("Failed to LocationUpdater location."); + Log.w("Failed to update location", e); } } }; @@ -299,34 +332,24 @@ public class CompassActivity extends AbstractActionBarActivity { } } - public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType, - final String info) { - coordinates.clear(); - if (coordinatesWithType != null) { - for (final IWaypoint coordinate : coordinatesWithType) { - if (coordinate != null) { - coordinates.add(coordinate); - } - } - } - + public static void startActivityWaypoint(final Context context, final Waypoint waypoint) { final Intent navigateIntent = new Intent(context, CompassActivity.class); - navigateIntent.putExtra(EXTRAS_COORDS, coords); - navigateIntent.putExtra(EXTRAS_GEOCODE, geocode); - if (null != displayedName) { - navigateIntent.putExtra(EXTRAS_NAME, displayedName); - } - navigateIntent.putExtra(EXTRAS_CACHE_INFO, info); + navigateIntent.putExtra(Intents.EXTRA_GEOCODE, waypoint.getGeocode()); + navigateIntent.putExtra(Intents.EXTRA_WAYPOINT_ID, waypoint.getId()); context.startActivity(navigateIntent); } - public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType) { - CompassActivity.startActivity(context, geocode, displayedName, coords, coordinatesWithType, null); + public static void startActivityPoint(final Context context, final Geopoint coords, final String displayedName) { + final Intent navigateIntent = new Intent(context, CompassActivity.class); + navigateIntent.putExtra(Intents.EXTRA_COORDS, coords); + navigateIntent.putExtra(Intents.EXTRA_NAME, displayedName); + context.startActivity(navigateIntent); } - public static void startActivity(final Context context, final Geocache cache) { - startActivity(context, cache.getGeocode(), cache.getName(), cache.getCoords(), null, - Formatter.formatCacheInfoShort(cache)); + public static void startActivityCache(final Context context, final Geocache cache) { + final Intent navigateIntent = new Intent(context, CompassActivity.class); + navigateIntent.putExtra(Intents.EXTRA_GEOCODE, cache.getGeocode()); + context.startActivity(navigateIntent); } } diff --git a/main/src/cgeo/geocaching/CreateShortcutActivity.java b/main/src/cgeo/geocaching/CreateShortcutActivity.java index ffcf81b..ecb7dc4 100644 --- a/main/src/cgeo/geocaching/CreateShortcutActivity.java +++ b/main/src/cgeo/geocaching/CreateShortcutActivity.java @@ -3,17 +3,53 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.maps.MapActivity; +import cgeo.geocaching.ui.dialog.Dialogs; +import cgeo.geocaching.ui.dialog.Dialogs.ItemWithIcon; +import cgeo.geocaching.utils.ImageUtils; import rx.functions.Action1; import android.content.Intent; import android.content.Intent.ShortcutIconResource; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.os.Bundle; +import java.util.ArrayList; +import java.util.List; + public class CreateShortcutActivity extends AbstractActionBarActivity { + private static class Shortcut implements ItemWithIcon { + + private final int titleResourceId; + private final int drawableResourceId; + private final Intent intent; + + /** + * shortcut with a separate icon + */ + public Shortcut(final int titleResourceId, final int drawableResourceId, final Intent intent) { + this.titleResourceId = titleResourceId; + this.drawableResourceId = drawableResourceId; + this.intent = intent; + } + + @Override + public int getIcon() { + return drawableResourceId; + } + + @Override + public String toString() { + return CgeoApplication.getInstance().getString(titleResourceId); + } + } + @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // init @@ -23,35 +59,82 @@ public class CreateShortcutActivity extends AbstractActionBarActivity { } private void promptForShortcut() { + final List<Shortcut> shortcuts = new ArrayList<>(); + + shortcuts.add(new Shortcut(R.string.live_map_button, R.drawable.main_live, new Intent(this, MapActivity.class))); + shortcuts.add(new Shortcut(R.string.caches_nearby_button, R.drawable.main_nearby, CacheListActivity.getNearestIntent(this))); + + // TODO: make logging activities ask for cache/trackable when being invoked externally + // shortcuts.add(new Shortcut(R.string.cache_menu_visit, new Intent(this, LogCacheActivity.class))); + // shortcuts.add(new Shortcut(R.string.trackable_log_touch, new Intent(this, LogTrackableActivity.class))); + + final Shortcut offlineShortcut = new Shortcut(R.string.list_title, R.drawable.main_stored, null); + shortcuts.add(offlineShortcut); + final Intent allIntent = new Intent(this, CacheListActivity.class); + allIntent.putExtra(Intents.EXTRA_LIST_ID, PseudoList.ALL_LIST.id); + shortcuts.add(new Shortcut(R.string.list_all_lists, R.drawable.main_stored, allIntent)); + shortcuts.add(new Shortcut(R.string.advanced_search_button, R.drawable.main_search, new Intent(this, SearchActivity.class))); + shortcuts.add(new Shortcut(R.string.any_button, R.drawable.main_any, new Intent(this, NavigateAnyPointActivity.class))); + shortcuts.add(new Shortcut(R.string.menu_history, R.drawable.main_stored, CacheListActivity.getHistoryIntent(this))); + + Dialogs.select(this, getString(R.string.create_shortcut), shortcuts, new Action1<Shortcut>() { + + @Override + public void call(final Shortcut shortcut) { + if (shortcut == offlineShortcut) { + promptForListShortcut(); + } + else { + createShortcutAndFinish(shortcut.toString(), shortcut.intent, shortcut.drawableResourceId); + } + } + }); + } + + protected void promptForListShortcut() { new StoredList.UserInterface(this).promptForListSelection(R.string.create_shortcut, new Action1<Integer>() { @Override public void call(final Integer listId) { - final Intent shortcut = createShortcut(listId); - setResult(RESULT_OK, shortcut); - - // finish activity to return the shortcut - finish(); + createOfflineListShortcut(listId); } - }, false, PseudoList.HISTORY_LIST.id); + }, true, PseudoList.NEW_LIST.id); } - protected Intent createShortcut(int listId) { + protected void createOfflineListShortcut(final int listId) { final StoredList list = DataStore.getList(listId); - if (list == null) { - return null; - } // target to be executed by the shortcut final Intent targetIntent = new Intent(this, CacheListActivity.class); targetIntent.putExtra(Intents.EXTRA_LIST_ID, list.id); - final ShortcutIconResource iconResource = Intent.ShortcutIconResource.fromContext(this, R.drawable.cgeo); // shortcut to be returned + createShortcutAndFinish(list.title, targetIntent, R.drawable.main_stored); + } + + private void createShortcutAndFinish(final String title, final Intent targetIntent, final int iconResourceId) { final Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, targetIntent); - intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, list.title); - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource); - return intent; + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); + if (iconResourceId == R.drawable.cgeo) { + final ShortcutIconResource iconResource = Intent.ShortcutIconResource.fromContext(this, iconResourceId); + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource); + } + else { + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createOverlay(iconResourceId)); + } + + setResult(RESULT_OK, intent); + + // finish activity to return the shortcut + finish(); + } + + private Bitmap createOverlay(final int drawableResourceId) { + final LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] { + res.getDrawable(drawableResourceId), res.getDrawable(R.drawable.cgeo) }); + layerDrawable.setLayerInset(0, 0, 0, 10, 10); + layerDrawable.setLayerInset(1, 50, 50, 0, 0); + return ImageUtils.convertToBitmap(layerDrawable); } } diff --git a/main/src/cgeo/geocaching/DataStore.java b/main/src/cgeo/geocaching/DataStore.java index e404b22..b7ca577 100644 --- a/main/src/cgeo/geocaching/DataStore.java +++ b/main/src/cgeo/geocaching/DataStore.java @@ -11,29 +11,34 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.files.LocalStorage; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.AbstractList; import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.search.SearchSuggestionCursor; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.FileUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.Version; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; -import rx.android.observables.AndroidObservable; +import rx.Observable; +import rx.Observable.OnSubscribe; +import rx.Subscriber; +import rx.android.app.AppObservable; +import rx.functions.Action0; import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func1; import rx.schedulers.Schedulers; -import rx.util.async.Async; import android.app.Activity; import android.app.ProgressDialog; @@ -58,6 +63,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; +import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -68,6 +74,7 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; public class DataStore { @@ -111,35 +118,32 @@ public class DataStore { "cg_caches.direction," + // 16 "cg_caches.distance," + // 17 "cg_caches.terrain," + // 18 - "cg_caches.latlon," + // 19 - "cg_caches.location," + // 20 - "cg_caches.personal_note," + // 21 - "cg_caches.shortdesc," + // 22 - "cg_caches.favourite_cnt," + // 23 - "cg_caches.rating," + // 24 - "cg_caches.votes," + // 25 - "cg_caches.myvote," + // 26 - "cg_caches.disabled," + // 27 - "cg_caches.archived," + // 28 - "cg_caches.members," + // 29 - "cg_caches.found," + // 30 - "cg_caches.favourite," + // 31 - "cg_caches.inventoryunknown," + // 32 - "cg_caches.onWatchlist," + // 33 - "cg_caches.reliable_latlon," + // 34 - "cg_caches.coordsChanged," + // 35 - "cg_caches.latitude," + // 36 - "cg_caches.longitude," + // 37 - "cg_caches.finalDefined," + // 38 - "cg_caches._id," + // 39 - "cg_caches.inventorycoins," + // 40 - "cg_caches.inventorytags," + // 41 - "cg_caches.logPasswordRequired"; // 42 - - //TODO: remove "latlon" field from cache table + "cg_caches.location," + // 19 + "cg_caches.personal_note," + // 20 + "cg_caches.shortdesc," + // 21 + "cg_caches.favourite_cnt," + // 22 + "cg_caches.rating," + // 23 + "cg_caches.votes," + // 24 + "cg_caches.myvote," + // 25 + "cg_caches.disabled," + // 26 + "cg_caches.archived," + // 27 + "cg_caches.members," + // 28 + "cg_caches.found," + // 29 + "cg_caches.favourite," + // 30 + "cg_caches.inventoryunknown," + // 31 + "cg_caches.onWatchlist," + // 32 + "cg_caches.reliable_latlon," + // 33 + "cg_caches.coordsChanged," + // 34 + "cg_caches.latitude," + // 35 + "cg_caches.longitude," + // 36 + "cg_caches.finalDefined," + // 37 + "cg_caches._id," + // 38 + "cg_caches.inventorycoins," + // 39 + "cg_caches.inventorytags," + // 40 + "cg_caches.logPasswordRequired"; // 41 /** The list of fields needed for mapping. */ - private static final String[] WAYPOINT_COLUMNS = new String[] { "_id", "geocode", "updated", "type", "prefix", "lookup", "name", "latlon", "latitude", "longitude", "note", "own", "visited" }; + private static final String[] WAYPOINT_COLUMNS = new String[] { "_id", "geocode", "updated", "type", "prefix", "lookup", "name", "latitude", "longitude", "note", "own", "visited" }; /** Number of days (as ms) after temporarily saved caches are deleted */ private final static long DAYS_AFTER_CACHE_IS_DELETED = 3 * 24 * 60 * 60 * 1000; @@ -147,7 +151,7 @@ public class DataStore { /** * holds the column indexes of the cache table to avoid lookups */ - private static CacheCache cacheCache = new CacheCache(); + private static final CacheCache cacheCache = new CacheCache(); private static SQLiteDatabase database = null; private static final int dbVersion = 68; public static final int customListIdOffset = 10; @@ -162,7 +166,7 @@ public class DataStore { private static final @NonNull String dbTableLogImages = "cg_logImages"; private static final @NonNull String dbTableLogsOffline = "cg_logs_offline"; private static final @NonNull String dbTableTrackables = "cg_trackables"; - private static final @NonNull String dbTableSearchDestionationHistory = "cg_search_destination_history"; + private static final @NonNull String dbTableSearchDestinationHistory = "cg_search_destination_history"; private static final @NonNull String dbCreateCaches = "" + "create table " + dbTableCaches + " (" + "_id integer primary key autoincrement, " @@ -183,7 +187,6 @@ public class DataStore { + "size text, " + "difficulty float, " + "terrain float, " - + "latlon text, " + "location text, " + "direction double, " + "distance double, " @@ -214,9 +217,7 @@ public class DataStore { + "create table " + dbTableLists + " (" + "_id integer primary key autoincrement, " + "title text not null, " - + "updated long not null, " - + "latitude double, " - + "longitude double " + + "updated long not null" + "); "; private static final String dbCreateAttributes = "" + "create table " + dbTableAttributes + " (" @@ -235,7 +236,6 @@ public class DataStore { + "prefix text, " + "lookup text, " + "name text, " - + "latlon text, " + "latitude double, " + "longitude double, " + "note text, " @@ -303,13 +303,23 @@ public class DataStore { + "); "; private static final String dbCreateSearchDestinationHistory = "" - + "create table " + dbTableSearchDestionationHistory + " (" + + "create table " + dbTableSearchDestinationHistory + " (" + "_id integer primary key autoincrement, " + "date long not null, " + "latitude double, " + "longitude double " + "); "; + private static final Observable<Integer> allCachesCountObservable = Observable.create(new OnSubscribe<Integer>() { + @Override + public void call(final Subscriber<? super Integer> subscriber) { + if (isInitialized()) { + subscriber.onNext(getAllCachesCount()); + subscriber.onCompleted(); + } + } + }).timeout(500, TimeUnit.MILLISECONDS).retry(10).subscribeOn(Schedulers.io()); + private static boolean newlyCreatedDatabase = false; private static boolean databaseCleaned = false; @@ -358,11 +368,12 @@ public class DataStore { } cacheCache.removeAllFromCache(); - PreparedStatements.clearPreparedStatements(); + PreparedStatement.clearPreparedStatements(); database.close(); database = null; } + @NonNull public static File getBackupFileInternal() { return new File(LocalStorage.getStorage(), "cgeo.sqlite"); } @@ -391,16 +402,15 @@ public class DataStore { * Move the database to/from external cgdata in a new thread, * showing a progress window * - * @param fromActivity */ public static void moveDatabase(final Activity fromActivity) { final ProgressDialog dialog = ProgressDialog.show(fromActivity, fromActivity.getString(R.string.init_dbmove_dbmove), fromActivity.getString(R.string.init_dbmove_running), true, false); - AndroidObservable.bindActivity(fromActivity, Async.fromCallable(new Func0<Boolean>() { + AppObservable.bindActivity(fromActivity, Observable.defer(new Func0<Observable<Boolean>>() { @Override - public Boolean call() { + public Observable<Boolean> call() { if (!LocalStorage.isExternalStorageAvailable()) { Log.w("Database was not moved: external memory not available"); - return false; + return Observable.just(false); } closeDb(); @@ -409,7 +419,7 @@ public class DataStore { if (!LocalStorage.copy(source, target)) { Log.e("Database could not be moved to " + target); init(); - return false; + return Observable.just(false); } if (!FileUtils.delete(source)) { Log.e("Original database could not be deleted during move"); @@ -418,7 +428,7 @@ public class DataStore { Log.i("Database was moved to " + target); init(); - return true; + return Observable.just(true); } })).subscribeOn(Schedulers.io()).subscribe(new Action1<Boolean>() { @Override @@ -430,14 +440,17 @@ public class DataStore { }); } + @NonNull private static File databasePath(final boolean internal) { return new File(internal ? LocalStorage.getInternalDbDirectory() : LocalStorage.getExternalDbDirectory(), dbName); } + @NonNull private static File databasePath() { return databasePath(!Settings.isDbOnSDCard()); } + @NonNull private static File databaseAlternatePath() { return databasePath(Settings.isDbOnSDCard()); } @@ -552,7 +565,7 @@ public class DataStore { try { db.execSQL(dbCreateSearchDestinationHistory); - Log.i("Added table " + dbTableSearchDestionationHistory + "."); + Log.i("Added table " + dbTableSearchDestinationHistory + "."); } catch (final Exception e) { Log.e("Failed to upgrade to ver. 52", e); } @@ -638,7 +651,6 @@ public class DataStore { + "size text, " + "difficulty float, " + "terrain float, " - + "latlon text, " + "location text, " + "direction double, " + "distance double, " @@ -665,7 +677,7 @@ public class DataStore { db.execSQL(dbCreateCachesTemp); db.execSQL("insert into " + dbTableCachesTemp + " select _id,updated,detailed,detailedupdate,visiteddate,geocode,reason,cacheid,guid,type,name,own,owner,owner_real," + - "hidden,hint,size,difficulty,terrain,latlon,location,direction,distance,latitude,longitude, 0," + + "hidden,hint,size,difficulty,terrain,location,direction,distance,latitude,longitude, 0," + "personal_note,shortdesc,description,favourite_cnt,rating,votes,myvote,disabled,archived,members,found,favourite,inventorycoins," + "inventorytags,inventoryunknown,onWatchlist from " + dbTableCaches); db.execSQL("drop table " + dbTableCaches); @@ -681,13 +693,12 @@ public class DataStore { + "prefix text, " + "lookup text, " + "name text, " - + "latlon text, " + "latitude double, " + "longitude double, " + "note text " + "); "; db.execSQL(dbCreateWaypointsTemp); - db.execSQL("insert into " + dbTableWaypointsTemp + " select _id, geocode, updated, type, prefix, lookup, name, latlon, latitude, longitude, note from " + dbTableWaypoints); + db.execSQL("insert into " + dbTableWaypointsTemp + " select _id, geocode, updated, type, prefix, lookup, name, latitude, longitude, note from " + dbTableWaypoints); db.execSQL("drop table " + dbTableWaypoints); db.execSQL("alter table " + dbTableWaypointsTemp + " rename to " + dbTableWaypoints); @@ -823,7 +834,7 @@ public class DataStore { private static void sanityChecks(final SQLiteDatabase db) { // Check that the history of searches is well formed as some dates seem to be missing according // to NPE traces. - final int staleHistorySearches = db.delete(dbTableSearchDestionationHistory, "date is null", null); + final int staleHistorySearches = db.delete(dbTableSearchDestinationHistory, "date is null", null); if (staleHistorySearches > 0) { Log.w(String.format(Locale.getDefault(), "DataStore.dbHelper.onOpen: removed %d bad search history entries", staleHistorySearches)); } @@ -871,15 +882,17 @@ public class DataStore { final File[] files = LocalStorage.getStorage().listFiles(); if (ArrayUtils.isNotEmpty(files)) { final Pattern oldFilePattern = Pattern.compile("^[GC|TB|EC|GK|O][A-Z0-9]{4,7}$"); - final SQLiteStatement select = db.compileStatement("select count(*) from " + dbTableCaches + " where geocode = ?"); + final SQLiteStatement select = PreparedStatement.CHECK_IF_PRESENT.getStatement(); final ArrayList<File> toRemove = new ArrayList<>(files.length); for (final File file : files) { if (file.isDirectory()) { final String geocode = file.getName(); if (oldFilePattern.matcher(geocode).find()) { - select.bindString(1, geocode); - if (select.simpleQueryForLong() == 0) { - toRemove.add(file); + synchronized (select) { + select.bindString(1, geocode); + if (select.simpleQueryForLong() == 0) { + toRemove.add(file); + } } } } @@ -887,15 +900,15 @@ public class DataStore { // Use a background thread for the real removal to avoid keeping the database locked // if we are called from within a transaction. - new Thread(new Runnable() { + Schedulers.io().createWorker().schedule(new Action0() { @Override - public void run() { + public void call() { for (final File dir : toRemove) { Log.i("Removing obsolete cache directory for " + dir.getName()); - LocalStorage.deleteDirectory(dir); + FileUtils.deleteDirectory(dir); } } - }).start(); + }); } } @@ -933,7 +946,7 @@ public class DataStore { int dataDetailed = 0; try { - Cursor cursor; + final Cursor cursor; if (StringUtils.isNotBlank(geocode)) { cursor = database.query( @@ -1000,18 +1013,18 @@ public class DataStore { final SQLiteStatement listId; final String value; if (StringUtils.isNotBlank(geocode)) { - listId = PreparedStatements.getListIdOfGeocode(); + listId = PreparedStatement.LIST_ID_OF_GEOCODE.getStatement(); value = geocode; } else { - listId = PreparedStatements.getListIdOfGuid(); + listId = PreparedStatement.LIST_ID_OF_GUID.getStatement(); value = guid; } synchronized (listId) { listId.bindString(1, value); - return listId.simpleQueryForLong() != StoredList.TEMPORARY_LIST_ID; + return listId.simpleQueryForLong() != StoredList.TEMPORARY_LIST.id; } - } catch (final SQLiteDoneException e) { + } catch (final SQLiteDoneException ignored) { // Do nothing, it only means we have no information on the cache } catch (final Exception e) { Log.e("DataStore.isOffline", e); @@ -1020,6 +1033,7 @@ public class DataStore { return false; } + @Nullable public static String getGeocodeForGuid(final String guid) { if (StringUtils.isBlank(guid)) { return null; @@ -1027,12 +1041,12 @@ public class DataStore { init(); try { - final SQLiteStatement description = PreparedStatements.getGeocodeOfGuid(); + final SQLiteStatement description = PreparedStatement.GEOCODE_OF_GUID.getStatement(); synchronized (description) { description.bindString(1, guid); return description.simpleQueryForString(); } - } catch (final SQLiteDoneException e) { + } catch (final SQLiteDoneException ignored) { // Do nothing, it only means we have no information on the cache } catch (final Exception e) { Log.e("DataStore.getGeocodeForGuid", e); @@ -1041,36 +1055,14 @@ public class DataStore { return null; } - public static String getCacheidForGeocode(final String geocode) { - if (StringUtils.isBlank(geocode)) { - return null; - } - init(); - - try { - final SQLiteStatement description = PreparedStatements.getCacheIdOfGeocode(); - synchronized (description) { - description.bindString(1, geocode); - return description.simpleQueryForString(); - } - } catch (final SQLiteDoneException e) { - // Do nothing, it only means we have no information on the cache - } catch (final Exception e) { - Log.e("DataStore.getCacheidForGeocode", e); - } - - return null; - } - /** * Save/store a cache to the CacheCache * * @param cache * the Cache to save in the CacheCache/DB - * @param saveFlags * */ - public static void saveCache(final Geocache cache, final EnumSet<LoadFlags.SaveFlag> saveFlags) { + public static void saveCache(final Geocache cache, final Set<LoadFlags.SaveFlag> saveFlags) { saveCaches(Collections.singletonList(cache), saveFlags); } @@ -1079,10 +1071,9 @@ public class DataStore { * * @param caches * the caches to save in the CacheCache/DB - * @param saveFlags * */ - public static void saveCaches(final Collection<Geocache> caches, final EnumSet<LoadFlags.SaveFlag> saveFlags) { + public static void saveCaches(final Collection<Geocache> caches, final Set<LoadFlags.SaveFlag> saveFlags) { if (CollectionUtils.isEmpty(caches)) { return; } @@ -1116,7 +1107,9 @@ public class DataStore { for (final Geocache cache : caches) { final String geocode = cache.getGeocode(); final Geocache existingCache = existingCaches.get(geocode); - final boolean dbUpdateRequired = !cache.gatherMissingFrom(existingCache) || cacheCache.getCacheFromCache(geocode) != null; + boolean dbUpdateRequired = !cache.gatherMissingFrom(existingCache) || cacheCache.getCacheFromCache(geocode) != null; + // parse the note AFTER merging the local information in + dbUpdateRequired |= cache.parseWaypointsFromNote(); cache.addStorageLocation(StorageLocation.CACHE); cacheCache.putCacheInCache(cache); @@ -1162,7 +1155,7 @@ public class DataStore { values.put("hidden", hiddenDate.getTime()); } values.put("hint", cache.getHint()); - values.put("size", cache.getSize() == null ? "" : cache.getSize().id); + values.put("size", cache.getSize().id); values.put("difficulty", cache.getDifficulty()); values.put("terrain", cache.getTerrain()); values.put("location", cache.getLocation()); @@ -1228,7 +1221,7 @@ public class DataStore { if (attributes.isEmpty()) { return; } - final SQLiteStatement statement = PreparedStatements.getInsertAttribute(); + final SQLiteStatement statement = PreparedStatement.INSERT_ATTRIBUTE.getStatement(); final long timestamp = System.currentTimeMillis(); for (final String attribute : attributes) { statement.bindString(1, geocode); @@ -1249,9 +1242,12 @@ public class DataStore { init(); database.beginTransaction(); - try { - final SQLiteStatement insertDestination = PreparedStatements.getInsertSearchDestination(destination); + final SQLiteStatement insertDestination = PreparedStatement.INSERT_SEARCH_DESTINATION.getStatement(); + insertDestination.bindLong(1, destination.getDate()); + final Geopoint coords = destination.getCoords(); + insertDestination.bindDouble(2, coords.getLatitude()); + insertDestination.bindDouble(3, coords.getLongitude()); insertDestination.executeInsert(); database.setTransactionSuccessful(); } catch (final Exception e) { @@ -1264,7 +1260,6 @@ public class DataStore { public static boolean saveWaypoints(final Geocache cache) { init(); database.beginTransaction(); - try { saveWaypointsWithoutTransaction(cache); database.setTransactionSuccessful(); @@ -1294,7 +1289,6 @@ public class DataStore { values.put("prefix", oneWaypoint.getPrefix()); values.put("lookup", oneWaypoint.getLookup()); values.put("name", oneWaypoint.getName()); - values.put("latlon", oneWaypoint.getLatlon()); putCoords(values, oneWaypoint.getCoords()); values.put("note", oneWaypoint.getNote()); values.put("own", oneWaypoint.isUserDefined() ? 1 : 0); @@ -1315,7 +1309,6 @@ public class DataStore { /** * remove all waypoints of the given cache, where the id is not in the given list * - * @param cache * @param remainingWaypointIds * ids of waypoints which shall not be deleted */ @@ -1329,7 +1322,7 @@ public class DataStore { * * @param values * a ContentValues to save coordinates in - * @param oneWaypoint + * @param coords * coordinates to save, or null to save empty coordinates */ private static void putCoords(final ContentValues values, final Geopoint coords) { @@ -1348,6 +1341,7 @@ public class DataStore { * index of the longitude column * @return the coordinates, or null if latitude or longitude is null or the coordinates are invalid */ + @Nullable private static Geopoint getCoords(final Cursor cursor, final int indexLat, final int indexLon) { if (cursor.isNull(indexLat) || cursor.isNull(indexLon)) { return null; @@ -1373,7 +1367,6 @@ public class DataStore { values.put("prefix", waypoint.getPrefix()); values.put("lookup", waypoint.getLookup()); values.put("name", waypoint.getName()); - values.put("latlon", waypoint.getLatlon()); putCoords(values, waypoint.getCoords()); values.put("note", waypoint.getNote()); values.put("own", waypoint.isUserDefined() ? 1 : 0); @@ -1410,7 +1403,7 @@ public class DataStore { final List<Image> spoilers = cache.getSpoilers(); if (CollectionUtils.isNotEmpty(spoilers)) { - final SQLiteStatement insertSpoiler = PreparedStatements.getInsertSpoiler(); + final SQLiteStatement insertSpoiler = PreparedStatement.INSERT_SPOILER.getStatement(); final long timestamp = System.currentTimeMillis(); for (final Image spoiler : spoilers) { insertSpoiler.bindString(1, geocode); @@ -1420,8 +1413,7 @@ public class DataStore { final String description = spoiler.getDescription(); if (description != null) { insertSpoiler.bindString(5, description); - } - else { + } else { insertSpoiler.bindNull(5); } insertSpoiler.executeInsert(); @@ -1429,11 +1421,21 @@ public class DataStore { } } - public static void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) { + public static void saveLogs(final String geocode, final Iterable<LogEntry> logs) { + database.beginTransaction(); + try { + saveLogsWithoutTransaction(geocode, logs); + database.setTransactionSuccessful(); + } finally { + database.endTransaction(); + } + } + + private static void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) { // TODO delete logimages referring these logs database.delete(dbTableLogs, "geocode = ?", new String[]{geocode}); - final SQLiteStatement insertLog = PreparedStatements.getInsertLog(); + final SQLiteStatement insertLog = PreparedStatement.INSERT_LOG.getStatement(); final long timestamp = System.currentTimeMillis(); for (final LogEntry log : logs) { insertLog.bindString(1, geocode); @@ -1446,7 +1448,7 @@ public class DataStore { insertLog.bindLong(8, log.friend ? 1 : 0); final long logId = insertLog.executeInsert(); if (log.hasLogImages()) { - final SQLiteStatement insertImage = PreparedStatements.getInsertLogImage(); + final SQLiteStatement insertImage = PreparedStatement.INSERT_LOG_IMAGE.getStatement(); for (final Image img : log.getLogImages()) { insertImage.bindLong(1, logId); insertImage.bindString(2, img.getTitle()); @@ -1464,7 +1466,7 @@ public class DataStore { final Map<LogType, Integer> logCounts = cache.getLogCounts(); if (MapUtils.isNotEmpty(logCounts)) { final Set<Entry<LogType, Integer>> logCountsItems = logCounts.entrySet(); - final SQLiteStatement insertLogCounts = PreparedStatements.getInsertLogCounts(); + final SQLiteStatement insertLogCounts = PreparedStatement.INSERT_LOG_COUNTS.getStatement(); final long timestamp = System.currentTimeMillis(); for (final Entry<LogType, Integer> pair : logCountsItems) { insertLogCounts.bindString(1, geocode); @@ -1526,6 +1528,7 @@ public class DataStore { } } + @Nullable public static Viewport getBounds(final Set<String> geocodes) { if (CollectionUtils.isEmpty(geocodes)) { return null; @@ -1542,6 +1545,7 @@ public class DataStore { * The Geocode GCXXXX * @return the loaded cache (if found). Can be null */ + @Nullable public static Geocache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) { if (StringUtils.isBlank(geocode)) { throw new IllegalArgumentException("geocode must not be empty"); @@ -1554,15 +1558,15 @@ public class DataStore { /** * Load caches. * - * @param geocodes * @return Set of loaded caches. Never null. */ + @NonNull public static Set<Geocache> loadCaches(final Collection<String> geocodes, final EnumSet<LoadFlag> loadFlags) { if (CollectionUtils.isEmpty(geocodes)) { return new HashSet<>(); } - final Set<Geocache> result = new HashSet<>(); + final Set<Geocache> result = new HashSet<>(geocodes.size()); final Set<String> remaining = new HashSet<>(geocodes); if (loadFlags.contains(LoadFlag.CACHE_BEFORE)) { @@ -1609,10 +1613,9 @@ public class DataStore { /** * Load caches. * - * @param geocodes - * @param loadFlags * @return Set of loaded caches. Never null. */ + @NonNull private static Set<Geocache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) { if (CollectionUtils.isEmpty(geocodes)) { return Collections.emptySet(); @@ -1640,7 +1643,7 @@ public class DataStore { int logIndex = -1; while (cursor.moveToNext()) { - final Geocache cache = DataStore.createCacheFromDatabaseContent(cursor); + final Geocache cache = createCacheFromDatabaseContent(cursor); if (loadFlags.contains(LoadFlag.ATTRIBUTES)) { cache.setAttributes(loadAttributes(cache.getGeocode())); @@ -1699,11 +1702,9 @@ public class DataStore { /** * Builds a where for a viewport with the size enhanced by 50%. * - * @param dbTable - * @param viewport - * @return */ + @NonNull private static StringBuilder buildCoordinateWhere(final String dbTable, final Viewport viewport) { return viewport.resize(1.5).sqlWhere(dbTable); } @@ -1711,9 +1712,9 @@ public class DataStore { /** * creates a Cache from the cursor. Doesn't next. * - * @param cursor * @return Cache from DB */ + @NonNull private static Geocache createCacheFromDatabaseContent(final Cursor cursor) { final Geocache cache = new Geocache(); @@ -1750,31 +1751,32 @@ public class DataStore { } cache.setTerrain(cursor.getFloat(18)); // do not set cache.location - cache.setCoords(getCoords(cursor, 36, 37)); - cache.setPersonalNote(cursor.getString(21)); + cache.setPersonalNote(cursor.getString(20)); // do not set cache.shortdesc // do not set cache.description - cache.setFavoritePoints(cursor.getInt(23)); - cache.setRating(cursor.getFloat(24)); - cache.setVotes(cursor.getInt(25)); - cache.setMyVote(cursor.getFloat(26)); - cache.setDisabled(cursor.getInt(27) == 1); - cache.setArchived(cursor.getInt(28) == 1); - cache.setPremiumMembersOnly(cursor.getInt(29) == 1); - cache.setFound(cursor.getInt(30) == 1); - cache.setFavorite(cursor.getInt(31) == 1); - cache.setInventoryItems(cursor.getInt(32)); - cache.setOnWatchlist(cursor.getInt(33) == 1); - cache.setReliableLatLon(cursor.getInt(34) > 0); - cache.setUserModifiedCoords(cursor.getInt(35) > 0); - cache.setFinalDefined(cursor.getInt(38) > 0); - cache.setLogPasswordRequired(cursor.getInt(42) > 0); + cache.setFavoritePoints(cursor.getInt(22)); + cache.setRating(cursor.getFloat(23)); + cache.setVotes(cursor.getInt(24)); + cache.setMyVote(cursor.getFloat(25)); + cache.setDisabled(cursor.getInt(26) == 1); + cache.setArchived(cursor.getInt(27) == 1); + cache.setPremiumMembersOnly(cursor.getInt(28) == 1); + cache.setFound(cursor.getInt(29) == 1); + cache.setFavorite(cursor.getInt(30) == 1); + cache.setInventoryItems(cursor.getInt(31)); + cache.setOnWatchlist(cursor.getInt(32) == 1); + cache.setReliableLatLon(cursor.getInt(33) > 0); + cache.setUserModifiedCoords(cursor.getInt(34) > 0); + cache.setCoords(getCoords(cursor, 35, 36)); + cache.setFinalDefined(cursor.getInt(37) > 0); + cache.setLogPasswordRequired(cursor.getInt(41) > 0); Log.d("Loading " + cache.toString() + " (" + cache.getListId() + ") from DB"); return cache; } + @Nullable public static List<String> loadAttributes(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -1792,6 +1794,7 @@ public class DataStore { GET_STRING_0); } + @Nullable public static Waypoint loadWaypoint(final int id) { if (id == 0) { return null; @@ -1818,6 +1821,7 @@ public class DataStore { return waypoint; } + @Nullable public static List<Waypoint> loadWaypoints(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -1840,6 +1844,7 @@ public class DataStore { }); } + @NonNull private static Waypoint createWaypointFromDatabaseContent(final Cursor cursor) { final String name = cursor.getString(cursor.getColumnIndex("name")); final WaypointType type = WaypointType.findById(cursor.getString(cursor.getColumnIndex("type"))); @@ -1850,13 +1855,13 @@ public class DataStore { waypoint.setGeocode(cursor.getString(cursor.getColumnIndex("geocode"))); waypoint.setPrefix(cursor.getString(cursor.getColumnIndex("prefix"))); waypoint.setLookup(cursor.getString(cursor.getColumnIndex("lookup"))); - waypoint.setLatlon(cursor.getString(cursor.getColumnIndex("latlon"))); waypoint.setCoords(getCoords(cursor, cursor.getColumnIndex("latitude"), cursor.getColumnIndex("longitude"))); waypoint.setNote(cursor.getString(cursor.getColumnIndex("note"))); return waypoint; } + @Nullable private static List<Image> loadSpoilers(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -1885,8 +1890,9 @@ public class DataStore { * * @return A list of previously entered destinations or an empty list. */ + @NonNull public static List<Destination> loadHistoryOfSearchedLocations() { - return queryToColl(dbTableSearchDestionationHistory, + return queryToColl(dbTableSearchDestinationHistory, new String[]{"_id", "date", "latitude", "longitude"}, "latitude IS NOT NULL AND longitude IS NOT NULL", null, @@ -1908,7 +1914,7 @@ public class DataStore { database.beginTransaction(); try { - database.delete(dbTableSearchDestionationHistory, null, null); + database.delete(dbTableSearchDestinationHistory, null, null); database.setTransactionSuccessful(); return true; } catch (final Exception e) { @@ -1921,7 +1927,6 @@ public class DataStore { } /** - * @param geocode * @return an immutable, non null list of logs */ @NonNull @@ -1935,7 +1940,7 @@ public class DataStore { init(); final Cursor cursor = database.rawQuery( - /* 0 1 2 3 4 5 6 7 8 9 10 */ + // 0 1 2 3 4 5 6 7 8 9 10 "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url" + " FROM " + dbTableLogs + " LEFT OUTER JOIN " + dbTableLogImages + " ON ( cg_logs._id = log_id ) WHERE geocode = ? ORDER BY date desc, cg_logs._id asc", new String[]{geocode}); @@ -1963,6 +1968,7 @@ public class DataStore { return Collections.unmodifiableList(logs); } + @Nullable public static Map<LogType, Integer> loadLogCounts(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -1970,7 +1976,7 @@ public class DataStore { init(); - final Map<LogType, Integer> logCounts = new HashMap<>(); + final Map<LogType, Integer> logCounts = new EnumMap<>(LogType.class); final Cursor cursor = database.query( dbTableLogCount, @@ -1991,6 +1997,7 @@ public class DataStore { return logCounts; } + @Nullable private static List<Trackable> loadInventory(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -2019,6 +2026,7 @@ public class DataStore { return trackables; } + @Nullable public static Trackable loadTrackable(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -2043,6 +2051,7 @@ public class DataStore { return trackable; } + @NonNull private static Trackable createTrackableFromDatabaseContent(final Cursor cursor) { final Trackable trackable = new Trackable(); trackable.setGeocode(cursor.getString(cursor.getColumnIndex("tbcode"))); @@ -2067,9 +2076,6 @@ public class DataStore { /** * Number of caches stored for a given type and/or list * - * @param cacheType - * @param list - * @return */ public static int getAllStoredCachesCount(final CacheType cacheType, final int list) { if (cacheType == null) { @@ -2081,37 +2087,29 @@ public class DataStore { init(); try { - final StringBuilder sql = new StringBuilder("select count(_id) from " + dbTableCaches + " where detailed = 1"); - String typeKey; - int reasonIndex; - if (cacheType != CacheType.ALL) { - sql.append(" and type = ?"); - typeKey = cacheType.id; - reasonIndex = 2; - } - else { - typeKey = "all_types"; - reasonIndex = 1; - } - String listKey; - if (list == PseudoList.ALL_LIST.id) { - sql.append(" and reason > 0"); - listKey = "all_list"; - } else { - sql.append(" and reason = ?"); - listKey = "list"; - } - - final String key = "CountCaches_" + typeKey + "_" + listKey; + final SQLiteStatement compiledStmnt; + synchronized (PreparedStatement.COUNT_TYPE_LIST) { + // All the statements here are used only once and are protected through the current synchronized block + if (list == PseudoList.ALL_LIST.id) { + if (cacheType == CacheType.ALL) { + compiledStmnt = PreparedStatement.COUNT_ALL_TYPES_ALL_LIST.getStatement(); + } else { + compiledStmnt = PreparedStatement.COUNT_TYPE_ALL_LIST.getStatement(); + compiledStmnt.bindString(1, cacheType.id); + } + } else { + if (cacheType == CacheType.ALL) { + compiledStmnt = PreparedStatement.COUNT_ALL_TYPES_LIST.getStatement(); + compiledStmnt.bindLong(1, list); + } else { + compiledStmnt = PreparedStatement.COUNT_TYPE_LIST.getStatement(); + compiledStmnt.bindString(1, cacheType.id); + compiledStmnt.bindLong(1, list); + } + } - final SQLiteStatement compiledStmnt = PreparedStatements.getStatement(key, sql.toString()); - if (cacheType != CacheType.ALL) { - compiledStmnt.bindString(1, cacheType.id); - } - if (list != PseudoList.ALL_LIST.id) { - compiledStmnt.bindLong(reasonIndex, list); + return (int) compiledStmnt.simpleQueryForLong(); } - return (int) compiledStmnt.simpleQueryForLong(); } catch (final Exception e) { Log.e("DataStore.loadAllStoredCachesCount", e); } @@ -2123,7 +2121,7 @@ public class DataStore { init(); try { - return (int) PreparedStatements.getCountHistoryCaches().simpleQueryForLong(); + return (int) PreparedStatement.HISTORY_COUNT.simpleQueryForLong(); } catch (final Exception e) { Log.e("DataStore.getAllHistoricCachesCount", e); } @@ -2131,6 +2129,7 @@ public class DataStore { return 0; } + @NonNull private static<T, U extends Collection<? super T>> U queryToColl(@NonNull final String table, final String[] columns, final String selection, @@ -2162,10 +2161,9 @@ public class DataStore { * * @param coords * the current coordinates to sort by distance, or null to sort by geocode - * @param cacheType - * @param listId * @return a non-null set of geocodes */ + @NonNull private static Set<String> loadBatchOfStoredGeocodes(final Geopoint coords, final CacheType cacheType, final int listId) { if (cacheType == null) { throw new IllegalArgumentException("cacheType must not be null"); @@ -2212,6 +2210,7 @@ public class DataStore { } } + @NonNull private static Set<String> loadBatchOfHistoricGeocodes(final boolean detailedOnly, final CacheType cacheType) { final StringBuilder selection = new StringBuilder("visiteddate > 0"); @@ -2243,11 +2242,13 @@ public class DataStore { } /** Retrieve all stored caches from DB */ + @NonNull public static SearchResult loadCachedInViewport(final Viewport viewport, final CacheType cacheType) { return loadInViewport(false, viewport, cacheType); } /** Retrieve stored caches from DB with listId >= 1 */ + @NonNull public static SearchResult loadStoredInViewport(final Viewport viewport, final CacheType cacheType) { return loadInViewport(true, viewport, cacheType); } @@ -2255,15 +2256,12 @@ public class DataStore { /** * Loads the geocodes of caches in a viewport from CacheCache and/or Database * - * @param stored - * True - query only stored caches, False - query cached ones as well - * @param centerLat - * @param centerLon - * @param spanLat - * @param spanLon - * @param cacheType - * @return Set with geocodes + * @param stored {@code true} to query caches stored in the database, {@code false} to also use the CacheCache + * @param viewport the viewport defining the area to scan + * @param cacheType the cache type + * @return the matching caches */ + @NonNull private static SearchResult loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) { final Set<String> geocodes = new HashSet<>(); @@ -2306,72 +2304,78 @@ public class DataStore { } /** - * Remove caches with listId = 0 - * - * @param more - * true = all caches false = caches stored 3 days or more before + * Remove caches with listId = 0 in the background. Once it has been executed once it will not do anything. + * This must be called from the UI thread to ensure synchronization of an internal variable. */ - public static void clean(final boolean more) { + public static void cleanIfNeeded(final Context context) { if (databaseCleaned) { return; } + databaseCleaned = true; - Log.d("Database clean: started"); + Schedulers.io().createWorker().schedule(new Action0() { + @Override + public void call() { + Log.d("Database clean: started"); + try { + final int version = Version.getVersionCode(context); + final Set<String> geocodes = new HashSet<>(); + if (version != Settings.getVersion()) { + queryToColl(dbTableCaches, + new String[]{"geocode"}, + "reason = 0", + null, + null, + null, + null, + null, + geocodes, + GET_STRING_0); + } else { + final long timestamp = System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED; + final String timestampString = Long.toString(timestamp); + queryToColl(dbTableCaches, + new String[]{"geocode"}, + "reason = 0 and detailed < ? and detailedupdate < ? and visiteddate < ?", + new String[]{timestampString, timestampString, timestampString}, + null, + null, + null, + null, + geocodes, + GET_STRING_0); + } - try { - Set<String> geocodes = new HashSet<>(); - if (more) { - queryToColl(dbTableCaches, - new String[]{"geocode"}, - "reason = 0", - null, - null, - null, - null, - null, - geocodes, - GET_STRING_0); - } else { - final long timestamp = System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED; - final String timestampString = Long.toString(timestamp); - queryToColl(dbTableCaches, - new String[]{"geocode"}, - "reason = 0 and detailed < ? and detailedupdate < ? and visiteddate < ?", - new String[]{timestampString, timestampString, timestampString}, - null, - null, - null, - null, - geocodes, - GET_STRING_0); - } + final Set<String> withoutOfflineLogs = exceptCachesWithOfflineLog(geocodes); + Log.d("Database clean: removing " + withoutOfflineLogs.size() + " geocaches from listId=0"); + removeCaches(withoutOfflineLogs, LoadFlags.REMOVE_ALL); - geocodes = exceptCachesWithOfflineLog(geocodes); + // This cleanup needs to be kept in place for about one year so that older log images records are + // cleaned. TO BE REMOVED AFTER 2015-03-24. + Log.d("Database clean: removing obsolete log images records"); + database.delete(dbTableLogImages, "log_id NOT IN (SELECT _id FROM " + dbTableLogs + ")", null); - if (!geocodes.isEmpty()) { - Log.d("Database clean: removing " + geocodes.size() + " geocaches from listId=0"); - removeCaches(geocodes, LoadFlags.REMOVE_ALL); - } + // Remove the obsolete "_others" directory where the user avatar used to be stored. + FileUtils.deleteDirectory(LocalStorage.getStorageDir("_others")); - // This cleanup needs to be kept in place for about one year so that older log images records are - // cleaned. TO BE REMOVED AFTER 2015-03-24. - Log.d("Database clean: removing obsolete log images records"); - database.delete(dbTableLogImages, "log_id NOT IN (SELECT _id FROM " + dbTableLogs + ")", null); - } catch (final Exception e) { - Log.w("DataStore.clean", e); - } + if (version > -1) { + Settings.setVersion(version); + } + } catch (final Exception e) { + Log.w("DataStore.clean", e); + } - Log.d("Database clean: finished"); - databaseCleaned = true; + Log.d("Database clean: finished"); + } + }); } /** * remove all geocodes from the given list of geocodes where an offline log exists * - * @param geocodes - * @return */ - private static Set<String> exceptCachesWithOfflineLog(final Set<String> geocodes) { + @NonNull + private static Set<String> exceptCachesWithOfflineLog(@NonNull final Set<String> geocodes) { if (geocodes.isEmpty()) { return geocodes; } @@ -2448,7 +2452,7 @@ public class DataStore { // Delete cache directories for (final String geocode : geocodes) { - LocalStorage.deleteDirectory(LocalStorage.getStorageDir(geocode)); + FileUtils.deleteDirectory(LocalStorage.getStorageDir(geocode)); } } } @@ -2480,6 +2484,7 @@ public class DataStore { return id != -1; } + @Nullable public static LogEntry loadLogOffline(final String geocode) { if (StringUtils.isBlank(geocode)) { return null; @@ -2528,13 +2533,11 @@ public class DataStore { init(); - final Set<String> geocodes = new HashSet<>(caches.size()); for (final Geocache cache : caches) { - geocodes.add(cache.getGeocode()); cache.setLogOffline(false); } - database.execSQL(String.format("DELETE FROM %s where %s", dbTableLogsOffline, whereGeocodeIn(geocodes))); + database.execSQL(String.format("DELETE FROM %s where %s", dbTableLogsOffline, whereGeocodeIn(Geocache.getGeocodes(caches)))); } public static boolean hasLogOffline(final String geocode) { @@ -2544,7 +2547,7 @@ public class DataStore { init(); try { - final SQLiteStatement logCount = PreparedStatements.getLogCountOfGeocode(); + final SQLiteStatement logCount = PreparedStatement.LOG_COUNT_OF_GEOCODE.getStatement(); synchronized (logCount) { logCount.bindString(1, geocode); return logCount.simpleQueryForLong() > 0; @@ -2565,8 +2568,7 @@ public class DataStore { database.beginTransaction(); try { - final SQLiteStatement setVisit = PreparedStatements.getUpdateVisitDate(); - + final SQLiteStatement setVisit = PreparedStatement.UPDATE_VISIT_DATE.getStatement(); for (final String geocode : geocodes) { setVisit.bindLong(1, visitedDate); setVisit.bindString(2, geocode); @@ -2584,7 +2586,7 @@ public class DataStore { final Resources res = CgeoApplication.getInstance().getResources(); final List<StoredList> lists = new ArrayList<>(); - lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong())); + lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatement.COUNT_CACHES_ON_STANDARD_LIST.simpleQueryForLong())); try { final String query = "SELECT l._id as _id, l.title as title, COUNT(c._id) as count" + @@ -2600,6 +2602,7 @@ public class DataStore { return lists; } + @NonNull private static ArrayList<StoredList> getListsFromCursor(final Cursor cursor) { final int indexId = cursor.getColumnIndex("_id"); final int indexTitle = cursor.getColumnIndex("title"); @@ -2613,6 +2616,7 @@ public class DataStore { }); } + @NonNull public static StoredList getList(final int id) { init(); if (id >= customListIdOffset) { @@ -2636,15 +2640,20 @@ public class DataStore { } // fall back to standard list in case of invalid list id - if (id == StoredList.STANDARD_LIST_ID || id >= customListIdOffset) { - return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong()); - } - - return null; + return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatement.COUNT_CACHES_ON_STANDARD_LIST.simpleQueryForLong()); } public static int getAllCachesCount() { - return (int) PreparedStatements.getCountAllCaches().simpleQueryForLong(); + return (int) PreparedStatement.COUNT_ALL_CACHES.simpleQueryForLong(); + } + + /** + * Count all caches in the background. + * + * @return an observable containing a unique element if the caches could be counted, or an error otherwise + */ + public static Observable<Integer> getAllCachesCountObservable() { + return allCachesCountObservable; } /** @@ -2710,7 +2719,6 @@ public class DataStore { /** * Remove a list. Caches in the list are moved to the standard list. * - * @param listId * @return true if the list got deleted, false else */ public static boolean removeList(final int listId) { @@ -2727,7 +2735,7 @@ public class DataStore { if (cnt > 0) { // move caches from deleted list to standard list - final SQLiteStatement moveToStandard = PreparedStatements.getMoveToStandardList(); + final SQLiteStatement moveToStandard = PreparedStatement.MOVE_TO_STANDARD_LIST.getStatement(); moveToStandard.bindLong(1, listId); moveToStandard.execute(); @@ -2759,7 +2767,7 @@ public class DataStore { } init(); - final SQLiteStatement move = PreparedStatements.getMoveToList(); + final SQLiteStatement move = PreparedStatement.MOVE_TO_LIST.getStatement(); database.beginTransaction(); try { @@ -2787,7 +2795,7 @@ public class DataStore { database.beginTransaction(); try { - database.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null); + database.delete(dbTableSearchDestinationHistory, "_id = " + destination.getId(), null); database.setTransactionSuccessful(); return true; } catch (final Exception e) { @@ -2802,9 +2810,8 @@ public class DataStore { /** * Load the lazily initialized fields of a cache and return them as partial cache (all other fields unset). * - * @param geocode - * @return */ + @NonNull public static Geocache loadCacheTexts(final String geocode) { final Geocache partial = new Geocache(); @@ -2835,7 +2842,7 @@ public class DataStore { } cursor.close(); - } catch (final SQLiteDoneException e) { + } catch (final SQLiteDoneException ignored) { // Do nothing, it only means we have no information on the cache } catch (final Exception e) { Log.e("DataStore.getCacheDescription", e); @@ -2862,11 +2869,12 @@ public class DataStore { * Creates the WHERE clause for matching multiple geocodes. This automatically converts all given codes to * UPPERCASE. */ + @NonNull private static StringBuilder whereGeocodeIn(final Collection<String> geocodes) { final StringBuilder whereExpr = new StringBuilder("geocode in ("); final Iterator<String> iterator = geocodes.iterator(); while (true) { - whereExpr.append(DatabaseUtils.sqlEscapeString(StringUtils.upperCase(iterator.next()))); + DatabaseUtils.appendEscapedSQLString(whereExpr, StringUtils.upperCase(iterator.next())); if (!iterator.hasNext()) { break; } @@ -2878,12 +2886,9 @@ public class DataStore { /** * Loads all Waypoints in the coordinate rectangle. * - * @param excludeDisabled - * @param excludeMine - * @param type - * @return */ + @NonNull public static Set<Waypoint> loadWaypoints(final Viewport viewport, final boolean excludeMine, final boolean excludeDisabled, final CacheType type) { final StringBuilder where = buildCoordinateWhere(dbTableWaypoints, viewport); if (excludeMine) { @@ -2914,103 +2919,71 @@ public class DataStore { } public static void saveChangedCache(final Geocache cache) { - DataStore.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.CACHE)); + DataStore.saveCache(cache, cache.inDatabase() ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.CACHE)); } - private static class PreparedStatements { - - private static HashMap<String, SQLiteStatement> statements = new HashMap<>(); - - public static SQLiteStatement getMoveToStandardList() { - return getStatement("MoveToStandardList", "UPDATE " + dbTableCaches + " SET reason = " + StoredList.STANDARD_LIST_ID + " WHERE reason = ?"); - } + private static enum PreparedStatement { - public static SQLiteStatement getMoveToList() { - return getStatement("MoveToList", "UPDATE " + dbTableCaches + " SET reason = ? WHERE geocode = ?"); - } + HISTORY_COUNT("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE visiteddate > 0"), + MOVE_TO_STANDARD_LIST("UPDATE " + dbTableCaches + " SET reason = " + StoredList.STANDARD_LIST_ID + " WHERE reason = ?"), + MOVE_TO_LIST("UPDATE " + dbTableCaches + " SET reason = ? WHERE geocode = ?"), + UPDATE_VISIT_DATE("UPDATE " + dbTableCaches + " SET visiteddate = ? WHERE geocode = ?"), + INSERT_LOG_IMAGE("INSERT INTO " + dbTableLogImages + " (log_id, title, url) VALUES (?, ?, ?)"), + INSERT_LOG_COUNTS("INSERT INTO " + dbTableLogCount + " (geocode, updated, type, count) VALUES (?, ?, ?, ?)"), + INSERT_SPOILER("INSERT INTO " + dbTableSpoilers + " (geocode, updated, url, title, description) VALUES (?, ?, ?, ?, ?)"), + LOG_COUNT_OF_GEOCODE("SELECT count(_id) FROM " + DataStore.dbTableLogsOffline + " WHERE geocode = ?"), + COUNT_CACHES_ON_STANDARD_LIST("SELECT count(_id) FROM " + dbTableCaches + " WHERE reason = " + StoredList.STANDARD_LIST_ID), + COUNT_ALL_CACHES("SELECT count(_id) FROM " + dbTableCaches + " WHERE reason >= " + StoredList.STANDARD_LIST_ID), + INSERT_LOG("INSERT INTO " + dbTableLogs + " (geocode, updated, type, author, log, date, found, friend) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"), + INSERT_ATTRIBUTE("INSERT INTO " + dbTableAttributes + " (geocode, updated, attribute) VALUES (?, ?, ?)"), + LIST_ID_OF_GEOCODE("SELECT reason FROM " + dbTableCaches + " WHERE geocode = ?"), + LIST_ID_OF_GUID("SELECT reason FROM " + dbTableCaches + " WHERE guid = ?"), + GEOCODE_OF_GUID("SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?"), + INSERT_SEARCH_DESTINATION("INSERT INTO " + dbTableSearchDestinationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)"), + COUNT_TYPE_ALL_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND type = ? AND reason > 0"), // See use of COUNT_TYPE_LIST for synchronization + COUNT_ALL_TYPES_ALL_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND reason > 0"), // See use of COUNT_TYPE_LIST for synchronization + COUNT_TYPE_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND type = ? AND reason = ?"), + COUNT_ALL_TYPES_LIST("SELECT COUNT(_id) FROM " + dbTableCaches + " WHERE detailed = 1 AND reason = ?"), // See use of COUNT_TYPE_LIST for synchronization + CHECK_IF_PRESENT("SELECT COUNT(*) FROM " + dbTableCaches + " WHERE geocode = ?"); - public static SQLiteStatement getUpdateVisitDate() { - return getStatement("UpdateVisitDate", "UPDATE " + dbTableCaches + " SET visiteddate = ? WHERE geocode = ?"); - } + private static final List<PreparedStatement> statements = new ArrayList<>(); - public static SQLiteStatement getInsertLogImage() { - return getStatement("InsertLogImage", "INSERT INTO " + dbTableLogImages + " (log_id, title, url) VALUES (?, ?, ?)"); - } + @Nullable + private volatile SQLiteStatement statement = null; // initialized lazily + final String query; - public static SQLiteStatement getInsertLogCounts() { - return getStatement("InsertLogCounts", "INSERT INTO " + dbTableLogCount + " (geocode, updated, type, count) VALUES (?, ?, ?, ?)"); + PreparedStatement(final String query) { + this.query = query; } - public static SQLiteStatement getInsertSpoiler() { - return getStatement("InsertSpoiler", "INSERT INTO " + dbTableSpoilers + " (geocode, updated, url, title, description) VALUES (?, ?, ?, ?, ?)"); + public long simpleQueryForLong() { + return getStatement().simpleQueryForLong(); } - public static SQLiteStatement getInsertSearchDestination(final Destination destination) { - final SQLiteStatement statement = getStatement("InsertSearch", "INSERT INTO " + dbTableSearchDestionationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)"); - statement.bindLong(1, destination.getDate()); - final Geopoint coords = destination.getCoords(); - statement.bindDouble(2, coords.getLatitude()); - statement.bindDouble(3, coords.getLongitude()); + private SQLiteStatement getStatement() { + if (statement == null) { + synchronized (statements) { + if (statement == null) { + init(); + statement = database.compileStatement(query); + statements.add(this); + } + } + } return statement; } private static void clearPreparedStatements() { - for (final SQLiteStatement statement : statements.values()) { - statement.close(); + for (final PreparedStatement preparedStatement : statements) { + final SQLiteStatement statement = preparedStatement.statement; + if (statement != null) { + statement.close(); + preparedStatement.statement = null; + } } statements.clear(); } - private static synchronized SQLiteStatement getStatement(final String key, final String query) { - SQLiteStatement statement = statements.get(key); - if (statement == null) { - init(); - statement = database.compileStatement(query); - statements.put(key, statement); - } - return statement; - } - - public static SQLiteStatement getCountHistoryCaches() { - return getStatement("HistoryCount", "select count(_id) from " + dbTableCaches + " where visiteddate > 0"); - } - - private static SQLiteStatement getLogCountOfGeocode() { - return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + DataStore.dbTableLogsOffline + " WHERE geocode = ?"); - } - - private static SQLiteStatement getCountCachesOnStandardList() { - return getStatement("CountStandardList", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason = " + StoredList.STANDARD_LIST_ID); - } - - private static SQLiteStatement getCountAllCaches() { - return getStatement("CountAllLists", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason >= " + StoredList.STANDARD_LIST_ID); - } - - private static SQLiteStatement getInsertLog() { - return getStatement("InsertLog", "INSERT INTO " + dbTableLogs + " (geocode, updated, type, author, log, date, found, friend) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); - } - - private static SQLiteStatement getInsertAttribute() { - return getStatement("InsertAttribute", "INSERT INTO " + dbTableAttributes + " (geocode, updated, attribute) VALUES (?, ?, ?)"); - } - - private static SQLiteStatement getListIdOfGeocode() { - return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE geocode = ?"); - } - - private static SQLiteStatement getListIdOfGuid() { - return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE guid = ?"); - } - - private static SQLiteStatement getCacheIdOfGeocode() { - return getStatement("cacheIdFromGeocode", "SELECT cacheid FROM " + dbTableCaches + " WHERE geocode = ?"); - } - - private static SQLiteStatement getGeocodeOfGuid() { - return getStatement("geocodeFromGuid", "SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?"); - } - } public static void saveVisitDate(final String geocode) { @@ -3018,9 +2991,10 @@ public class DataStore { } public static void markDropped(final List<Geocache> caches) { - moveToList(caches, StoredList.TEMPORARY_LIST_ID); + moveToList(caches, StoredList.TEMPORARY_LIST.id); } + @Nullable public static Viewport getBounds(final String geocode) { if (geocode == null) { return null; @@ -3033,11 +3007,13 @@ public class DataStore { setVisitDate(Arrays.asList(selected), 0); } + @NonNull public static SearchResult getBatchOfStoredCaches(final Geopoint coords, final CacheType cacheType, final int listId) { final Set<String> geocodes = DataStore.loadBatchOfStoredGeocodes(coords, cacheType, listId); return new SearchResult(geocodes, DataStore.getAllStoredCachesCount(cacheType, listId)); } + @NonNull public static SearchResult getHistoryOfCaches(final boolean detailedOnly, final CacheType cacheType) { final Set<String> geocodes = DataStore.loadBatchOfHistoricGeocodes(detailedOnly, cacheType); return new SearchResult(geocodes, DataStore.getAllHistoryCachesCount()); @@ -3051,6 +3027,7 @@ public class DataStore { return false; } + @NonNull public static Set<String> getCachedMissingFromSearch(final SearchResult searchResult, final Set<Tile> tiles, final IConnector connector, final int maxZoom) { // get cached CacheListActivity @@ -3081,6 +3058,7 @@ public class DataStore { return missingFromSearch; } + @Nullable public static Cursor findSuggestions(final String searchTerm) { // require 3 characters, otherwise there are to many results if (StringUtils.length(searchTerm) < 3) { @@ -3116,6 +3094,7 @@ public class DataStore { cursor.close(); } + @NonNull private static String getSuggestionArgument(final String input) { return "%" + StringUtils.trim(input) + "%"; } @@ -3143,6 +3122,7 @@ public class DataStore { cursor.close(); } + @NonNull public static String[] getSuggestions(final String table, final String column, final String input) { try { final Cursor cursor = database.rawQuery("SELECT DISTINCT " + column @@ -3152,26 +3132,31 @@ public class DataStore { return cursorToColl(cursor, new LinkedList<String>(), GET_STRING_0).toArray(new String[cursor.getCount()]); } catch (final RuntimeException e) { Log.e("cannot get suggestions from " + table + "->" + column + " for input '" + input + "'", e); - return new String[0]; + return ArrayUtils.EMPTY_STRING_ARRAY; } } + @NonNull public static String[] getSuggestionsOwnerName(final String input) { return getSuggestions(dbTableCaches, "owner_real", input); } + @NonNull public static String[] getSuggestionsTrackableCode(final String input) { return getSuggestions(dbTableTrackables, "tbcode", input); } + @NonNull public static String[] getSuggestionsFinderName(final String input) { return getSuggestions(dbTableLogs, "author", input); } + @NonNull public static String[] getSuggestionsGeocode(final String input) { return getSuggestions(dbTableCaches, "geocode", input); } + @NonNull public static String[] getSuggestionsKeyword(final String input) { return getSuggestions(dbTableCaches, "name", input); } @@ -3180,6 +3165,7 @@ public class DataStore { * * @return list of last caches opened in the details view, ordered by most recent first */ + @NonNull public static ArrayList<Geocache> getLastOpenedCaches() { final List<String> geocodes = Settings.getLastOpenedCaches(); final Set<Geocache> cachesSet = DataStore.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB); diff --git a/main/src/cgeo/geocaching/Destination.java b/main/src/cgeo/geocaching/Destination.java index 10d51be..1990d5d 100644 --- a/main/src/cgeo/geocaching/Destination.java +++ b/main/src/cgeo/geocaching/Destination.java @@ -1,6 +1,6 @@ package cgeo.geocaching; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; public final class Destination implements ICoordinates { diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java index d49308e..ce279bf 100644 --- a/main/src/cgeo/geocaching/EditWaypointActivity.java +++ b/main/src/cgeo/geocaching/EditWaypointActivity.java @@ -7,11 +7,12 @@ import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.DistanceParser; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.location.DistanceParser; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.dialog.CoordinatesInputDialog; import cgeo.geocaching.ui.dialog.Dialogs; @@ -66,11 +67,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C @ViewById(R.id.modify_cache_coordinates_local) protected RadioButton modifyLocal; @Extra(Intents.EXTRA_GEOCODE) protected String geocode = null; - @Extra(Intents.EXTRA_WAYPOINT_ID) protected int id = -1; - /** - * number of waypoints that the corresponding cache has until now - */ - @Extra(Intents.EXTRA_COUNT) protected int wpCount = 0; + @Extra(Intents.EXTRA_WAYPOINT_ID) protected int waypointId = -1; @InstanceState protected int waypointTypeSelectorPosition = -1; @@ -89,14 +86,14 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C */ private Geocache cache; - private Handler loadWaypointHandler = new Handler() { + private final Handler loadWaypointHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { try { if (waypoint == null) { - Log.d("No waypoint loaded to edit. id= " + id); - id = -1; + Log.d("No waypoint loaded to edit. id= " + waypointId); + waypointId = -1; } else { geocode = waypoint.getGeocode(); prefix = waypoint.getPrefix(); @@ -119,14 +116,23 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C } Dialogs.moveCursorToEnd(note); } - final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY); - setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache); + new AsyncTask<Void, Void, Geocache>() { + @Override + protected Geocache doInBackground(final Void... params) { + return DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY); + } + + @Override + protected void onPostExecute(final Geocache cache) { + setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache); + } + }.execute(); } if (own) { initializeWaypointTypeSelector(); } - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.e("EditWaypointActivity.loadWaypointHandler", e); } finally { if (waitDialog != null) { @@ -138,17 +144,17 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C }; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.editwaypoint_activity); - if (StringUtils.isBlank(geocode) && id <= 0) { + if (StringUtils.isBlank(geocode) && waypointId <= 0) { showToast(res.getString(R.string.err_waypoint_cache_unknown)); finish(); return; } - if (id <= 0) { + if (waypointId <= 0) { setTitle(res.getString(R.string.waypoint_add_title)); } else { setTitle(res.getString(R.string.waypoint_edit_title)); @@ -159,11 +165,11 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C addWaypoint.setOnClickListener(new SaveWaypointListener()); - List<String> wayPointNames = new ArrayList<>(); - for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) { + final List<String> wayPointNames = new ArrayList<>(); + for (final WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) { wayPointNames.add(wpt.getL10n()); } - ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, wayPointNames); + final ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, wayPointNames); waypointName.setAdapter(adapter); if (savedInstanceState != null) { @@ -174,7 +180,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache); } - if (id > 0) { // existing waypoint + if (waypointId > 0) { // existing waypoint waitDialog = ProgressDialog.show(this, null, res.getString(R.string.waypoint_loading), true); waitDialog.setCancelable(true); @@ -189,7 +195,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C disableSuggestions(distanceView); } - private void setCoordsModificationVisibility(IConnector con, Geocache cache) { + private void setCoordsModificationVisibility(final IConnector con, final Geocache cache) { if (cache != null && (cache.getType() == CacheType.MYSTERY || cache.getType() == CacheType.MULTI)) { coordinatesGroup.setVisibility(View.VISIBLE); modifyBoth.setVisibility(con.supportsOwnCoordinates() ? View.VISIBLE : View.GONE); @@ -205,18 +211,23 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C } private void initializeWaypointTypeSelector() { - ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, POSSIBLE_WAYPOINT_TYPES.toArray(new WaypointType[POSSIBLE_WAYPOINT_TYPES.size()])); + final ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, POSSIBLE_WAYPOINT_TYPES.toArray(new WaypointType[POSSIBLE_WAYPOINT_TYPES.size()])); wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); waypointTypeSelector.setAdapter(wpAdapter); waypointTypeSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override - public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) { + public void onItemSelected(final AdapterView<?> parent, final View v, final int pos, final long id) { + final String oldDefaultName = waypointTypeSelectorPosition >= 0 ? getDefaultWaypointName(POSSIBLE_WAYPOINT_TYPES.get(waypointTypeSelectorPosition)) : StringUtils.EMPTY; waypointTypeSelectorPosition = pos; + final String currentName = waypointName.getText().toString().trim(); + if (StringUtils.isBlank(currentName) || oldDefaultName.equals(currentName)) { + waypointName.setText(getDefaultWaypointName(getSelectedWaypointType())); + } } @Override - public void onNothingSelected(AdapterView<?> parent) { + public void onNothingSelected(final AdapterView<?> parent) { } }); @@ -249,17 +260,13 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C private void initializeDistanceUnitSelector() { distanceUnits = new ArrayList<>(Arrays.asList(res.getStringArray(R.array.distance_units))); if (initViews) { - distanceUnitSelector.setSelection(Settings.isUseImperialUnits() ? 2 : 0); //0:m, 2:ft + distanceUnitSelector.setSelection(Settings.useImperialUnits() ? 2 : 0); //0:m, 2:ft } } final private GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override - public void updateGeoData(final IGeoData geo) { - if (geo.getCoords() == null) { - return; - } - + public void updateGeoData(final GeoData geo) { try { buttonLat.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); buttonLon.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); @@ -274,10 +281,10 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C @Override public void run() { try { - waypoint = DataStore.loadWaypoint(id); + waypoint = DataStore.loadWaypoint(waypointId); loadWaypointHandler.sendMessage(Message.obtain()); - } catch (Exception e) { + } catch (final Exception e) { Log.e("EditWaypointActivity.loadWaypoint.run", e); } } @@ -286,28 +293,71 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C private class CoordDialogListener implements View.OnClickListener { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { Geopoint gp = null; try { gp = new Geopoint(buttonLat.getText().toString(), buttonLon.getText().toString()); - } catch (Geopoint.ParseException e) { + } catch (final Geopoint.ParseException ignored) { // button text is blank when creating new waypoint } - Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); - CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(cache, gp, app.currentGeo()); - coordsDialog.setCancelable(true); - coordsDialog.show(getSupportFragmentManager(),"wpeditdialog"); + final Geopoint geopoint = gp; + new AsyncTask<Void, Void, Geocache>() { + @Override + protected Geocache doInBackground(final Void... params) { + return DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + } + + @Override + protected void onPostExecute(final Geocache cache) { + final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(cache, geopoint, Sensors.getInstance().currentGeo()); + coordsDialog.setCancelable(true); + coordsDialog.show(getSupportFragmentManager(), "wpeditdialog"); + } + }.execute(); } } @Override - public void updateCoordinates(Geopoint gp) { + public void updateCoordinates(final Geopoint gp) { buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); } + /** + * Suffix the waypoint type with a running number to get a default name. + * + * @param type + * type to create a new default name for + * + */ + private String getDefaultWaypointName(final WaypointType type) { + final ArrayList<String> wpNames = new ArrayList<>(); + for (final Waypoint waypoint : cache.getWaypoints()) { + wpNames.add(waypoint.getName()); + } + // try final and trailhead without index + if (type == WaypointType.FINAL || type == WaypointType.TRAILHEAD) { + if (!wpNames.contains(type.getL10n())) { + return type.getL10n(); + } + } + // for other types add an index by default, which is highest found index + 1 + int max = 0; + for (int i = 0; i < 30; i++) { + if (wpNames.contains(type.getL10n() + " " + i)) { + max = i; + } + } + return type.getL10n() + " " + (max + 1); + } + + private WaypointType getSelectedWaypointType() { + final int selectedTypeIndex = waypointTypeSelector.getSelectedItemPosition(); + return selectedTypeIndex >= 0 ? POSSIBLE_WAYPOINT_TYPES.get(selectedTypeIndex) : waypoint.getWaypointType(); + } + public static final int SUCCESS = 0; public static final int UPLOAD_START = 1; public static final int UPLOAD_ERROR = 2; @@ -318,7 +368,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C private class SaveWaypointListener implements View.OnClickListener { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { final String bearingText = bearing.getText().toString(); // combine distance from EditText and distanceUnit saved from Spinner final String distanceText = distanceView.getText().toString() + distanceUnits.get(distanceUnitSelector.getSelectedItemPosition()); @@ -336,17 +386,12 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C if (StringUtils.isNotBlank(latText) && StringUtils.isNotBlank(lonText)) { try { coords = new Geopoint(latText, lonText); - } catch (Geopoint.ParseException e) { + } catch (final Geopoint.ParseException e) { showToast(res.getString(e.resource)); return; } } else { - final IGeoData geo = app.currentGeo(); - if (geo.getCoords() == null) { - showToast(res.getString(R.string.err_point_curr_position_unavailable)); - return; - } - coords = geo.getCoords(); + coords = Sensors.getInstance().currentGeo().getCoords(); } if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) { @@ -354,7 +399,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C double bearing; try { bearing = Double.parseDouble(bearingText); - } catch (NumberFormatException e) { + } catch (final NumberFormatException ignored) { Dialogs.message(EditWaypointActivity.this, R.string.err_point_bear_and_dist_title, R.string.err_point_bear_and_dist); return; } @@ -362,8 +407,8 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C double distance; try { distance = DistanceParser.parseDistance(distanceText, - !Settings.isUseImperialUnits()); - } catch (NumberFormatException e) { + !Settings.useImperialUnits()); + } catch (final NumberFormatException ignored) { showToast(res.getString(R.string.err_parse_dist)); return; } @@ -371,25 +416,22 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C coords = coords.project(bearing, distance); } - // if no name is given, just give the waypoint its number as name final String givenName = waypointName.getText().toString().trim(); - final String name = StringUtils.isNotEmpty(givenName) ? givenName : res.getString(R.string.waypoint) + " " + (wpCount + 1); + final String name = StringUtils.defaultIfBlank(givenName, getDefaultWaypointName(getSelectedWaypointType())); final String noteText = note.getText().toString().trim(); final Geopoint coordsToSave = coords; - final int selectedTypeIndex = waypointTypeSelector.getSelectedItemPosition(); - final WaypointType type = selectedTypeIndex >= 0 ? POSSIBLE_WAYPOINT_TYPES.get(selectedTypeIndex) : waypoint.getWaypointType(); + final WaypointType type = getSelectedWaypointType(); final boolean visited = visitedCheckBox.isChecked(); final ProgressDialog progress = ProgressDialog.show(EditWaypointActivity.this, getString(R.string.waypoint), getString(R.string.waypoint_being_saved), true); final Handler finishHandler = new Handler() { @Override - public void handleMessage(Message msg) { - // TODO: The order of showToast, progress.dismiss and finish is different in these cases. Why? + public void handleMessage(final Message msg) { switch (msg.what) { case UPLOAD_SUCCESS: - showToast(getString(R.string.waypoint_coordinates_has_been_modified_on_website, coordsToSave)); progress.dismiss(); finish(); + showToast(getString(R.string.waypoint_coordinates_has_been_modified_on_website, coordsToSave)); break; case SUCCESS: progress.dismiss(); @@ -422,7 +464,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C class SaveWptTask extends AsyncTask<Void, Void, Void> { @Override - protected Void doInBackground(Void... params) { + protected Void doInBackground(final Void... params) { final Waypoint waypoint = new Waypoint(name, type, own); waypoint.setGeocode(geocode); waypoint.setPrefix(prefix); @@ -430,14 +472,14 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C waypoint.setCoords(coordsToSave); waypoint.setNote(noteText); waypoint.setVisited(visited); - waypoint.setId(id); + waypoint.setId(waypointId); - Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); if (cache == null) { finishHandler.sendEmptyMessage(SAVE_ERROR); return null; } - Waypoint oldWaypoint = cache.getWaypointById(id); + final Waypoint oldWaypoint = cache.getWaypointById(waypointId); if (cache.addOrChangeWaypoint(waypoint, true)) { DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); if (!StaticMapsProvider.hasAllStaticMapsForWaypoint(geocode, waypoint)) { @@ -460,7 +502,7 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C finishHandler.sendEmptyMessage(UPLOAD_START); if (cache.supportsOwnCoordinates()) { - boolean result = uploadModifiedCoords(cache, waypoint.getCoords()); + final boolean result = uploadModifiedCoords(cache, waypoint.getCoords()); finishHandler.sendEmptyMessage(result ? SUCCESS : UPLOAD_ERROR); } else { showToast(getString(R.string.waypoint_coordinates_couldnt_be_modified_on_website)); @@ -485,10 +527,10 @@ public class EditWaypointActivity extends AbstractActionBarActivity implements C } public static void startActivityEditWaypoint(final Context context, final Geocache cache, final int waypointId) { - EditWaypointActivity_.intent(context).geocode(cache.getGeocode()).id(waypointId).start(); + EditWaypointActivity_.intent(context).geocode(cache.getGeocode()).waypointId(waypointId).start(); } public static void startActivityAddWaypoint(final Context context, final Geocache cache) { - EditWaypointActivity_.intent(context).geocode(cache.getGeocode()).wpCount(cache.getWaypoints().size()).start(); + EditWaypointActivity_.intent(context).geocode(cache.getGeocode()).start(); } } diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index d9b2856..033196c 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -12,22 +12,20 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.connector.gc.UncertainProperty; -import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.files.GPXParser; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.CancellableHandler; -import cgeo.geocaching.utils.DateUtils; import cgeo.geocaching.utils.ImageUtils; import cgeo.geocaching.utils.LazyInitializedList; import cgeo.geocaching.utils.Log; @@ -40,7 +38,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; -import org.apache.commons.collections4.Predicate; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -50,18 +47,17 @@ import org.eclipse.jdt.annotation.Nullable; import rx.Scheduler; import rx.Subscription; import rx.functions.Action0; +import rx.schedulers.Schedulers; import android.app.Activity; import android.content.Intent; import android.content.res.Resources; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.Parcelable; import android.text.Html; -import android.text.Html.ImageGetter; import java.io.File; import java.util.ArrayList; @@ -69,10 +65,9 @@ import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.EnumMap; import java.util.EnumSet; -import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -80,16 +75,18 @@ import java.util.Set; import java.util.regex.Pattern; /** - * Internal c:geo representation of a "cache" + * Internal representation of a "cache" */ -public class Geocache implements ICache, IWaypoint { +public class Geocache implements IWaypoint { private static final int OWN_WP_PREFIX_OFFSET = 17; private long updated = 0; private long detailedUpdate = 0; private long visitedDate = 0; - private int listId = StoredList.TEMPORARY_LIST_ID; + private int listId = StoredList.TEMPORARY_LIST.id; private boolean detailed = false; + + @NonNull private String geocode = ""; private String cacheId = ""; private String guid = ""; @@ -102,7 +99,7 @@ public class Geocache implements ICache, IWaypoint { * lazy initialized */ private String hint = null; - private CacheSize size = CacheSize.UNKNOWN; + @NonNull private CacheSize size = CacheSize.UNKNOWN; private float difficulty = 0; private float terrain = 0; private Float direction = null; @@ -137,19 +134,19 @@ public class Geocache implements ICache, IWaypoint { private final LazyInitializedList<String> attributes = new LazyInitializedList<String>() { @Override public List<String> call() { - return DataStore.loadAttributes(geocode); + return inDatabase() ? DataStore.loadAttributes(geocode) : new LinkedList<String>(); } }; private final LazyInitializedList<Waypoint> waypoints = new LazyInitializedList<Waypoint>() { @Override public List<Waypoint> call() { - return DataStore.loadWaypoints(geocode); + return inDatabase() ? DataStore.loadWaypoints(geocode) : new LinkedList<Waypoint>(); } }; private List<Image> spoilers = null; private List<Trackable> inventory = null; - private Map<LogType, Integer> logCounts = new HashMap<>(); + private Map<LogType, Integer> logCounts = new EnumMap<>(LogType.class); private boolean userModifiedCoords = false; // temporary values private boolean statusChecked = false; @@ -163,10 +160,6 @@ public class Geocache implements ICache, IWaypoint { private Handler changeNotificationHandler = null; - // Images whose URL contains one of those patterns will not be available on the Images tab - // for opening into an external application. - private final String[] NO_EXTERNAL = new String[]{"geocheck.org"}; - /** * Create a new cache. To be used everywhere except for the GPX parser */ @@ -178,7 +171,7 @@ public class Geocache implements ICache, IWaypoint { * Cache constructor to be used by the GPX parser only. This constructor explicitly sets several members to empty * lists. * - * @param gpxParser + * @param gpxParser ignored parameter allowing to select this constructor */ public Geocache(final GPXParser gpxParser) { setReliableLatLon(true); @@ -220,7 +213,7 @@ public class Geocache implements ICache, IWaypoint { // if parsed cache is not yet detailed and stored is, the information of // the parsed cache will be overwritten if (!detailed && other.detailed) { - detailed = other.detailed; + detailed = true; detailedUpdate = other.detailedUpdate; // boolean values must be enumerated here. Other types are assigned outside this if-statement reliableLatLon = other.reliableLatLon; @@ -251,7 +244,7 @@ public class Geocache implements ICache, IWaypoint { if (visitedDate == 0) { visitedDate = other.visitedDate; } - if (listId == StoredList.TEMPORARY_LIST_ID) { + if (listId == StoredList.TEMPORARY_LIST.id) { listId = other.listId; } if (StringUtils.isBlank(geocode)) { @@ -279,7 +272,7 @@ public class Geocache implements ICache, IWaypoint { if (!detailed && StringUtils.isBlank(getHint())) { hint = other.getHint(); } - if (size == null || CacheSize.UNKNOWN == size) { + if (size == CacheSize.UNKNOWN) { size = other.size; } if (difficulty == 0) { @@ -455,11 +448,7 @@ public class Geocache implements ICache, IWaypoint { ActivityMixin.showToast(fromActivity, fromActivity.getResources().getString(R.string.err_cannot_log_visit)); return; } - final Intent logVisitIntent = new Intent(fromActivity, LogCacheActivity.class); - logVisitIntent.putExtra(LogCacheActivity.EXTRAS_ID, cacheId); - logVisitIntent.putExtra(LogCacheActivity.EXTRAS_GEOCODE, geocode); - - fromActivity.startActivity(logVisitIntent); + fromActivity.startActivity(LogCacheActivity.getLogCacheIntent(fromActivity, cacheId, geocode)); } public void logOffline(final Activity fromActivity, final LogType logType) { @@ -491,11 +480,15 @@ public class Geocache implements ICache, IWaypoint { notifyChange(); } + @NonNull public List<LogType> getPossibleLogTypes() { return getConnector().getPossibleLogTypes(this); } public void openInBrowser(final Activity fromActivity) { + if (getUrl() == null) { + return; + } final Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getLongUrl())); // Check if cgeo is the default, show the chooser to let the user choose a browser @@ -514,19 +507,11 @@ public class Geocache implements ICache, IWaypoint { } } - - private String getCacheUrl() { - return getConnector().getCacheUrl(this); - } - + @NonNull private IConnector getConnector() { return ConnectorFactory.getConnector(this); } - public boolean canOpenInBrowser() { - return getCacheUrl() != null; - } - public boolean supportsRefresh() { return getConnector() instanceof ISearchByGeocode; } @@ -551,11 +536,11 @@ public class Geocache implements ICache, IWaypoint { return getConnector().supportsOwnCoordinates(); } + @NonNull public ILoggingManager getLoggingManager(final LogCacheActivity activity) { return getConnector().getLoggingManager(activity, this); } - @Override public float getDifficulty() { return difficulty; } @@ -565,35 +550,30 @@ public class Geocache implements ICache, IWaypoint { return geocode; } - @Override + /** + * @return displayed owner, might differ from the real owner + */ public String getOwnerDisplayName() { return ownerDisplayName; } - @Override + @NonNull public CacheSize getSize() { - if (size == null) { - return CacheSize.UNKNOWN; - } return size; } - @Override public float getTerrain() { return terrain; } - @Override public boolean isArchived() { return BooleanUtils.isTrue(archived); } - @Override public boolean isDisabled() { return BooleanUtils.isTrue(disabled); } - @Override public boolean isPremiumMembersOnly() { return BooleanUtils.isTrue(premiumMembersOnly); } @@ -602,20 +582,27 @@ public class Geocache implements ICache, IWaypoint { this.premiumMembersOnly = members; } - @Override + /** + * + * @return {@code true} if the user is the owner of the cache, {@code false} otherwise + */ public boolean isOwner() { return getConnector().isOwner(this); } - @Override + /** + * @return GC username of the (actual) owner, might differ from the owner. Never empty. + */ + @NonNull public String getOwnerUserId() { return ownerUserId; } /** * Attention, calling this method may trigger a database access for the cache! + * + * @return the decrypted hint */ - @Override public String getHint() { initializeCacheTexts(); assertTextNotNull(hint, "Hint"); @@ -635,7 +622,6 @@ public class Geocache implements ICache, IWaypoint { /** * Attention, calling this method may trigger a database access for the cache! */ - @Override public String getDescription() { initializeCacheTexts(); assertTextNotNull(description, "Description"); @@ -647,18 +633,25 @@ public class Geocache implements ICache, IWaypoint { */ private void initializeCacheTexts() { if (description == null || shortdesc == null || hint == null || location == null) { - final Geocache partial = DataStore.loadCacheTexts(this.getGeocode()); - if (description == null) { - setDescription(partial.getDescription()); - } - if (shortdesc == null) { - setShortDescription(partial.getShortDescription()); - } - if (hint == null) { - setHint(partial.getHint()); - } - if (location == null) { - setLocation(partial.getLocation()); + if (inDatabase()) { + final Geocache partial = DataStore.loadCacheTexts(this.getGeocode()); + if (description == null) { + setDescription(partial.getDescription()); + } + if (shortdesc == null) { + setShortDescription(partial.getShortDescription()); + } + if (hint == null) { + setHint(partial.getHint()); + } + if (location == null) { + setLocation(partial.getLocation()); + } + } else { + description = StringUtils.defaultString(description); + shortdesc = StringUtils.defaultString(shortdesc); + hint = StringUtils.defaultString(hint); + location = StringUtils.defaultString(location); } } } @@ -666,7 +659,6 @@ public class Geocache implements ICache, IWaypoint { /** * Attention, calling this method may trigger a database access for the cache! */ - @Override public String getShortDescription() { initializeCacheTexts(); assertTextNotNull(shortdesc, "Short description"); @@ -678,7 +670,6 @@ public class Geocache implements ICache, IWaypoint { return name; } - @Override public String getCacheId() { if (StringUtils.isBlank(cacheId) && getConnector().equals(GCConnector.getInstance())) { return String.valueOf(GCConstants.gccodeToGCId(geocode)); @@ -687,7 +678,6 @@ public class Geocache implements ICache, IWaypoint { return cacheId; } - @Override public String getGuid() { return guid; } @@ -695,14 +685,12 @@ public class Geocache implements ICache, IWaypoint { /** * Attention, calling this method may trigger a database access for the cache! */ - @Override public String getLocation() { initializeCacheTexts(); assertTextNotNull(location, "Location"); return location; } - @Override public String getPersonalNote() { // non premium members have no personal notes, premium members have an empty string by default. // map both to null, so other code doesn't need to differentiate @@ -713,15 +701,13 @@ public class Geocache implements ICache, IWaypoint { return getConnector() instanceof ISearchByCenter; } - public void shareCache(final Activity fromActivity, final Resources res) { - if (geocode == null) { - return; - } - + public void shareCache(@NonNull final Activity fromActivity, final Resources res) { final Intent intent = getShareIntent(); fromActivity.startActivity(Intent.createChooser(intent, res.getText(R.string.cache_menu_share))); } + + @NonNull public Intent getShareIntent() { final StringBuilder subject = new StringBuilder("Geocache "); subject.append(geocode); @@ -732,20 +718,25 @@ public class Geocache implements ICache, IWaypoint { final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_SUBJECT, subject.toString()); - intent.putExtra(Intent.EXTRA_TEXT, getUrl()); + intent.putExtra(Intent.EXTRA_TEXT, StringUtils.defaultString(getUrl())); return intent; } + @Nullable public String getUrl() { return getConnector().getCacheUrl(this); } + @Nullable public String getLongUrl() { return getConnector().getLongCacheUrl(this); } - public String getCgeoUrl() { return getConnector().getCacheUrl(this); } + @Nullable + public String getCgeoUrl() { + return getConnector().getCacheUrl(this); + } public boolean supportsGCVote() { return StringUtils.startsWithIgnoreCase(geocode, "GC"); @@ -755,12 +746,14 @@ public class Geocache implements ICache, IWaypoint { this.description = description; } - @Override public boolean isFound() { return BooleanUtils.isTrue(found); } - @Override + /** + * + * @return {@code true} if the user has put a favorite point onto this cache + */ public boolean isFavorite() { return BooleanUtils.isTrue(favorite); } @@ -769,18 +762,16 @@ public class Geocache implements ICache, IWaypoint { this.favorite = favorite; } - @Override @Nullable public Date getHiddenDate() { return hidden; } - @Override + @NonNull public List<String> getAttributes() { return attributes.getUnderlyingList(); } - @Override public List<Trackable> getInventory() { return inventory; } @@ -792,22 +783,25 @@ public class Geocache implements ICache, IWaypoint { spoilers.add(spoiler); } - @Override + @NonNull public List<Image> getSpoilers() { return ListUtils.unmodifiableList(ListUtils.emptyIfNull(spoilers)); } - @Override + /** + * @return a statistic how often the caches has been found, disabled, archived etc. + */ public Map<LogType, Integer> getLogCounts() { return logCounts; } - @Override public int getFavoritePoints() { return favoritePoints; } - @Override + /** + * @return the normalized cached name to be used for sorting, taking into account the numerical parts in the name + */ public String getNameForSorting() { if (null == nameForSorting) { nameForSorting = name; @@ -908,8 +902,6 @@ public class Geocache implements ICache, IWaypoint { /** * Set reliable coordinates - * - * @param coords */ public void setCoords(final Geopoint coords) { this.coords = new UncertainProperty<>(coords); @@ -917,9 +909,6 @@ public class Geocache implements ICache, IWaypoint { /** * Set unreliable coordinates from a certain map zoom level - * - * @param coords - * @param zoomlevel */ public void setCoords(final Geopoint coords, final int zoomlevel) { this.coords = new UncertainProperty<>(coords, zoomlevel); @@ -976,7 +965,9 @@ public class Geocache implements ICache, IWaypoint { this.inventoryItems = inventoryItems; } - @Override + /** + * @return {@code true} if the cache is on the user's watchlist, {@code false} otherwise + */ public boolean isOnWatchlist() { return BooleanUtils.isTrue(onWatchlist); } @@ -990,6 +981,7 @@ public class Geocache implements ICache, IWaypoint { * * @return always non <code>null</code> */ + @NonNull public List<Waypoint> getWaypoints() { return waypoints.getUnderlyingList(); } @@ -1028,7 +1020,7 @@ public class Geocache implements ICache, IWaypoint { */ @NonNull public List<LogEntry> getLogs() { - return DataStore.loadLogs(geocode); + return inDatabase() ? DataStore.loadLogs(geocode) : Collections.<LogEntry>emptyList(); } /** @@ -1069,7 +1061,7 @@ public class Geocache implements ICache, IWaypoint { this.directionImg = directionImg; } - public void setGeocode(final String geocode) { + public void setGeocode(@NonNull final String geocode) { this.geocode = StringUtils.upperCase(geocode); } @@ -1097,13 +1089,8 @@ public class Geocache implements ICache, IWaypoint { this.hint = hint; } - public void setSize(final CacheSize size) { - if (size == null) { - this.size = CacheSize.UNKNOWN; - } - else { - this.size = size; - } + public void setSize(@NonNull final CacheSize size) { + this.size = size; } public void setDifficulty(final float difficulty) { @@ -1160,7 +1147,6 @@ public class Geocache implements ICache, IWaypoint { * * @returns Never null */ - @Override public CacheType getType() { return cacheType.getValue(); } @@ -1203,6 +1189,13 @@ public class Geocache implements ICache, IWaypoint { } /** + * Check if this cache instance comes from or has been stored into the database. + */ + public boolean inDatabase() { + return storageLocation.contains(StorageLocation.DATABASE); + } + + /** * @param waypoint * Waypoint to add to the cache * @param saveToDatabase @@ -1214,7 +1207,9 @@ public class Geocache implements ICache, IWaypoint { waypoint.setGeocode(geocode); if (waypoint.getId() < 0) { // this is a new waypoint - assignUniquePrefix(waypoint); + if (StringUtils.isBlank(waypoint.getPrefix())) { + assignUniquePrefix(waypoint); + } waypoints.add(waypoint); if (waypoint.isFinalWithCoords()) { finalDefined = true; @@ -1249,13 +1244,14 @@ public class Geocache implements ICache, IWaypoint { } for (int i = OWN_WP_PREFIX_OFFSET; i < 100; i++) { - final String prefixCandidate = StringUtils.leftPad(String.valueOf(i), 2, '0'); + final String prefixCandidate = String.valueOf(i); if (!assignedPrefixes.contains(prefixCandidate)) { waypoint.setPrefix(prefixCandidate); - break; + return; } } + throw new IllegalStateException("too many waypoints, unable to assign unique prefix"); } public boolean hasWaypoints() { @@ -1341,8 +1337,6 @@ public class Geocache implements ICache, IWaypoint { /** * deletes any waypoint - * - * @param waypoint */ public void deleteWaypointForce(final Waypoint waypoint) { @@ -1389,12 +1383,15 @@ public class Geocache implements ICache, IWaypoint { /** * Detect coordinates in the personal note and convert them to user defined waypoints. Works by rule of thumb. */ - public void parseWaypointsFromNote() { + public boolean parseWaypointsFromNote() { + boolean changed = false; for (final Waypoint waypoint : Waypoint.parseWaypointsFromNote(StringUtils.defaultString(getPersonalNote()))) { if (!hasIdenticalWaypoint(waypoint.getCoords())) { addOrChangeWaypoint(waypoint, false); + changed = true; } } + return changed; } private boolean hasIdenticalWaypoint(final Geopoint point) { @@ -1432,7 +1429,7 @@ public class Geocache implements ICache, IWaypoint { } public void store(final CancellableHandler handler) { - store(StoredList.TEMPORARY_LIST_ID, handler); + store(StoredList.TEMPORARY_LIST.id, handler); } public void store(final int listId, final CancellableHandler handler) { @@ -1457,8 +1454,8 @@ public class Geocache implements ICache, IWaypoint { return "cache"; } - public Subscription drop(final Handler handler, final Scheduler scheduler) { - return scheduler.createWorker().schedule(new Action0() { + public Subscription drop(final Handler handler) { + return Schedulers.io().createWorker().schedule(new Action0() { @Override public void call() { try { @@ -1476,54 +1473,37 @@ public class Geocache implements ICache, IWaypoint { DataStore.removeCache(getGeocode(), EnumSet.of(RemoveFlag.CACHE)); } - public void checkFields() { - if (StringUtils.isBlank(getGeocode())) { - Log.w("geo code not parsed correctly for " + geocode); - } - if (StringUtils.isBlank(getName())) { - Log.w("name not parsed correctly for " + geocode); - } - if (StringUtils.isBlank(getGuid())) { - Log.w("guid not parsed correctly for " + geocode); - } - if (getTerrain() == 0.0) { - Log.w("terrain not parsed correctly for " + geocode); - } - if (getDifficulty() == 0.0) { - Log.w("difficulty not parsed correctly for " + geocode); - } - if (StringUtils.isBlank(getOwnerDisplayName())) { - Log.w("owner display name not parsed correctly for " + geocode); - } - if (StringUtils.isBlank(getOwnerUserId())) { - Log.w("owner user id real not parsed correctly for " + geocode); - } - if (getHiddenDate() == null) { - Log.w("hidden not parsed correctly for " + geocode); - } - if (getFavoritePoints() < 0) { - Log.w("favoriteCount not parsed correctly for " + geocode); - } - if (getSize() == null) { - Log.w("size not parsed correctly for " + geocode); - } - if (getType() == null || getType() == CacheType.UNKNOWN) { - Log.w("type not parsed correctly for " + geocode); - } - if (getCoords() == null) { - Log.w("coordinates not parsed correctly for " + geocode); - } - if (StringUtils.isBlank(getLocation())) { - Log.w("location not parsed correctly for " + geocode); + private void warnIncorrectParsingIf(final boolean incorrect, final String field) { + if (incorrect) { + Log.w(field + " not parsed correctly for " + geocode); } } + private void warnIncorrectParsingIfBlank(final String str, final String field) { + warnIncorrectParsingIf(StringUtils.isBlank(str), field); + } + + public void checkFields() { + warnIncorrectParsingIfBlank(getGeocode(), "geo"); + warnIncorrectParsingIfBlank(getName(), "name"); + warnIncorrectParsingIfBlank(getGuid(), "guid"); + warnIncorrectParsingIf(getTerrain() == 0.0, "terrain"); + warnIncorrectParsingIf(getDifficulty() == 0.0, "difficulty"); + warnIncorrectParsingIfBlank(getOwnerDisplayName(), "owner"); + warnIncorrectParsingIfBlank(getOwnerUserId(), "owner"); + warnIncorrectParsingIf(getHiddenDate() == null, "hidden"); + warnIncorrectParsingIf(getFavoritePoints() < 0, "favoriteCount"); + warnIncorrectParsingIf(getSize() == CacheSize.UNKNOWN, "size"); + warnIncorrectParsingIf(getType() == null || getType() == CacheType.UNKNOWN, "type"); + warnIncorrectParsingIf(getCoords() == null, "coordinates"); + warnIncorrectParsingIfBlank(getLocation(), "location"); + } + public Subscription refresh(final CancellableHandler handler, final Scheduler scheduler) { return scheduler.createWorker().schedule(new Action0() { @Override public void call() { refreshSynchronous(handler); - handler.sendEmptyMessage(CancellableHandler.DONE); } }); } @@ -1614,7 +1594,7 @@ public class Geocache implements ICache, IWaypoint { RxUtils.waitForCompletion(StaticMapsProvider.downloadMaps(cache), imgGetter.waitForEndObservable(handler)); if (handler != null) { - handler.sendMessage(Message.obtain()); + handler.sendEmptyMessage(CancellableHandler.DONE); } } catch (final Exception e) { Log.e("Geocache.storeCache", e); @@ -1627,7 +1607,7 @@ public class Geocache implements ICache, IWaypoint { return null; } - if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (DataStore.isOffline(geocode, guid) || DataStore.isThere(geocode, guid, true, true))) { + if (!forceReload && listId == StoredList.TEMPORARY_LIST.id && (DataStore.isOffline(geocode, guid) || DataStore.isThere(geocode, guid, true, true))) { final SearchResult search = new SearchResult(); final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : DataStore.getGeocodeForGuid(guid); search.addGeocode(realGeocode); @@ -1635,7 +1615,7 @@ public class Geocache implements ICache, IWaypoint { } // if we have no geocode, we can't dynamically select the handler, but must explicitly use GC - if (geocode == null && guid != null) { + if (geocode == null) { return GCConnector.getInstance().searchByGeocode(null, guid, handler); } @@ -1655,9 +1635,9 @@ public class Geocache implements ICache, IWaypoint { * * @return start time in minutes after midnight */ - public String guessEventTimeMinutes() { + public int guessEventTimeMinutes() { if (!isEventCache()) { - return null; + return -1; } final String hourLocalized = CgeoApplication.getInstance().getString(R.string.cache_time_full_hours); @@ -1669,7 +1649,7 @@ public class Geocache implements ICache, IWaypoint { // 17 - 20 o'clock patterns.add(Pattern.compile("\\b(\\d{1,2})(?:\\.00)?" + "\\s*(?:-|[a-z]+)\\s*" + "(?:\\d{1,2})(?:\\.00)?" + "\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE)); // 12 o'clock, 12.00 o'clock - patterns.add(Pattern.compile("\\b(\\d{1,2})(?:\\.00)?\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE)); + patterns.add(Pattern.compile("\\b(\\d{1,2})(?:\\.(00|15|30|45))?\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE)); } final String searchText = getShortDescription() + ' ' + getDescription(); @@ -1679,64 +1659,25 @@ public class Geocache implements ICache, IWaypoint { try { final int hours = Integer.parseInt(matcher.group(1)); int minutes = 0; - if (matcher.groupCount() >= 2) { + if (matcher.groupCount() >= 2 && !StringUtils.isEmpty(matcher.group(2))) { minutes = Integer.parseInt(matcher.group(2)); } if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) { - return String.valueOf(hours * 60 + minutes); + return hours * 60 + minutes; } - } catch (final NumberFormatException e) { + } catch (final NumberFormatException ignored) { // cannot happen, but static code analysis doesn't know } } } - return null; - } - - /** - * check whether the cache has a given attribute - * - * @param attribute - * @param yes - * true if we are looking for the attribute_yes version, false for the attribute_no version - * @return - */ - public boolean hasAttribute(final CacheAttribute attribute, final boolean yes) { - Geocache fullCache = DataStore.loadCache(getGeocode(), EnumSet.of(LoadFlag.ATTRIBUTES)); - if (fullCache == null) { - fullCache = this; - } - return fullCache.getAttributes().contains(attribute.getAttributeName(yes)); + return -1; } public boolean hasStaticMap() { return StaticMapsProvider.hasStaticMap(this); } - public static final Predicate<Geocache> hasStaticMap = new Predicate<Geocache>() { - @Override - public boolean evaluate(final Geocache cache) { - return cache.hasStaticMap(); - } - }; - - private void addDescriptionImagesUrls(final Collection<Image> images) { - final Set<String> urls = new LinkedHashSet<>(); - for (final Image image : images) { - urls.add(image.getUrl()); - } - Html.fromHtml(getDescription(), new ImageGetter() { - @Override - public Drawable getDrawable(final String source) { - if (!urls.contains(source) && !ImageUtils.containsPattern(source, NO_EXTERNAL)) { - images.add(new Image(source, geocode)); - urls.add(source); - } - return null; - } - }, null); - } - + @NonNull public Collection<Image> getImages() { final LinkedList<Image> result = new LinkedList<>(); result.addAll(getSpoilers()); @@ -1744,22 +1685,23 @@ public class Geocache implements ICache, IWaypoint { for (final LogEntry log : getLogs()) { result.addAll(log.getLogImages()); } - final Set<String> urls = new HashSet<>(result.size()); - for (final Image image : result) { - urls.add(image.getUrl()); - } - addDescriptionImagesUrls(result); + ImageUtils.addImagesFromHtml(result, geocode, getShortDescription(), getDescription()); return result; } - // Add spoilers stored locally in /sdcard/GeocachePhotos + /** + * Add spoilers stored locally in <tt>/sdcard/GeocachePhotos</tt>. If a cache is named GC123ABC, the + * directory will be <tt>/sdcard/GeocachePhotos/C/B/GC123ABC/</tt>. + * + * @param spoilers the list to add to + */ private void addLocalSpoilersTo(final List<Image> spoilers) { if (StringUtils.length(geocode) >= 2) { final String suffix = StringUtils.right(geocode, 2); - final File baseDir = new File(Environment.getExternalStorageDirectory().toString(), "GeocachePhotos"); + final File baseDir = new File(Environment.getExternalStorageDirectory(), "GeocachePhotos"); final File lastCharDir = new File(baseDir, suffix.substring(1)); final File secondToLastCharDir = new File(lastCharDir, suffix.substring(0, 1)); - final File finalDir = new File(secondToLastCharDir, getGeocode()); + final File finalDir = new File(secondToLastCharDir, geocode); final File[] files = finalDir.listFiles(); if (files != null) { for (final File image : files) { @@ -1805,18 +1747,17 @@ public class Geocache implements ICache, IWaypoint { return getConnector().getWaypointGpxId(prefix, geocode); } + @NonNull public String getWaypointPrefix(final String name) { return getConnector().getWaypointPrefix(name); } /** * Get number of overall finds for a cache, or 0 if the number of finds is not known. - * - * @return */ public int getFindsCount() { if (getLogCounts().isEmpty()) { - setLogCounts(DataStore.loadLogCounts(getGeocode())); + setLogCounts(inDatabase() ? DataStore.loadLogCounts(getGeocode()) : Collections.<LogType, Integer>emptyMap()); } final Integer logged = getLogCounts().get(LogType.FOUND_IT); if (logged != null) { @@ -1829,12 +1770,13 @@ public class Geocache implements ICache, IWaypoint { return (getType().applyDistanceRule() || hasUserModifiedCoords()) && getConnector() == GCConnector.getInstance(); } + @NonNull public LogType getDefaultLogType() { if (isEventCache()) { final Date eventDate = getHiddenDate(); - final boolean expired = DateUtils.isPastEvent(this); + final boolean expired = CalendarUtils.isPastEvent(this); - if (hasOwnLog(LogType.WILL_ATTEND) || expired || (eventDate != null && DateUtils.daysSince(eventDate.getTime()) == 0)) { + if (hasOwnLog(LogType.WILL_ATTEND) || expired || (eventDate != null && CalendarUtils.daysSince(eventDate.getTime()) == 0)) { return hasOwnLog(LogType.ATTENDED) ? LogType.NOTE : LogType.ATTENDED; } return LogType.WILL_ATTEND; @@ -1848,4 +1790,30 @@ public class Geocache implements ICache, IWaypoint { return LogType.FOUND_IT; } + /** + * Get the geocodes of a collection of caches. + * + * @param caches a collection of caches + * @return the non-blank geocodes of the caches + */ + @NonNull + public static Set<String> getGeocodes(@NonNull final Collection<Geocache> caches) { + final Set<String> geocodes = new HashSet<>(caches.size()); + for (final Geocache cache : caches) { + final String geocode = cache.getGeocode(); + if (StringUtils.isNotBlank(geocode)) { + geocodes.add(geocode); + } + } + return geocodes; + } + + /** + * Show the hint as toast message. If no hint is available, a default "no hint available" will be shown instead. + */ + public void showHintToast(final Activity activity) { + final String hint = getHint(); + ActivityMixin.showToast(activity, StringUtils.defaultIfBlank(hint, activity.getString(R.string.cache_hint_not_available))); + } + } diff --git a/main/src/cgeo/geocaching/GpxFileListActivity.java b/main/src/cgeo/geocaching/GpxFileListActivity.java index dae52c4..352dbab 100644 --- a/main/src/cgeo/geocaching/GpxFileListActivity.java +++ b/main/src/cgeo/geocaching/GpxFileListActivity.java @@ -1,63 +1,64 @@ -package cgeo.geocaching;
-
-import cgeo.geocaching.connector.ConnectorFactory;
-import cgeo.geocaching.connector.IConnector;
-import cgeo.geocaching.files.AbstractFileListActivity;
-import cgeo.geocaching.files.GPXImporter;
-import cgeo.geocaching.list.StoredList;
-import cgeo.geocaching.settings.Settings;
-import cgeo.geocaching.ui.GPXListAdapter;
-
-import org.apache.commons.lang3.StringUtils;
-
-import android.app.Activity;
-import android.content.Intent;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.List;
-
-public class GpxFileListActivity extends AbstractFileListActivity<GPXListAdapter> {
-
- public GpxFileListActivity() {
- super(new String[] { "gpx", "loc", "zip" });
- }
-
- @Override
- protected GPXListAdapter getAdapter(List<File> files) {
- return new GPXListAdapter(this, files);
- }
-
- @Override
- protected List<File> getBaseFolders() {
- return Collections.singletonList(new File(Settings.getGpxImportDir()));
- }
-
- public static void startSubActivity(Activity fromActivity, int listId) {
- final Intent intent = new Intent(fromActivity, GpxFileListActivity.class);
- intent.putExtra(Intents.EXTRA_LIST_ID, StoredList.getConcreteList(listId));
- fromActivity.startActivityForResult(intent, 0);
- }
-
- @Override
- protected boolean filenameBelongsToList(final String filename) {
- if (super.filenameBelongsToList(filename)) {
- if (StringUtils.endsWithIgnoreCase(filename, GPXImporter.ZIP_FILE_EXTENSION)) {
- for (IConnector connector : ConnectorFactory.getConnectors()) {
- if (connector.isZippedGPXFile(filename)) {
- return true;
- }
- }
- return false;
- }
- // filter out waypoint files
- return !StringUtils.containsIgnoreCase(filename, GPXImporter.WAYPOINTS_FILE_SUFFIX);
- }
- return false;
- }
-
- public int getListId() {
- return listId;
- }
-
-}
+package cgeo.geocaching; + +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.files.AbstractFileListActivity; +import cgeo.geocaching.files.GPXImporter; +import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.ui.GPXListAdapter; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; + +import android.app.Activity; +import android.content.Intent; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +public class GpxFileListActivity extends AbstractFileListActivity<GPXListAdapter> { + + public GpxFileListActivity() { + super(new String[] { "gpx", "loc", "zip" }); + } + + @Override + protected GPXListAdapter getAdapter(final List<File> files) { + return new GPXListAdapter(this, files); + } + + @Override + protected List<File> getBaseFolders() { + return Collections.singletonList(new File(Settings.getGpxImportDir())); + } + + public static void startSubActivity(final Activity fromActivity, final int listId) { + final Intent intent = new Intent(fromActivity, GpxFileListActivity.class); + intent.putExtra(Intents.EXTRA_LIST_ID, StoredList.getConcreteList(listId)); + fromActivity.startActivityForResult(intent, 0); + } + + @Override + protected boolean filenameBelongsToList(@NonNull final String filename) { + if (super.filenameBelongsToList(filename)) { + if (StringUtils.endsWithIgnoreCase(filename, GPXImporter.ZIP_FILE_EXTENSION)) { + for (final IConnector connector : ConnectorFactory.getConnectors()) { + if (connector.isZippedGPXFile(filename)) { + return true; + } + } + return false; + } + // filter out waypoint files + return !StringUtils.containsIgnoreCase(filename, GPXImporter.WAYPOINTS_FILE_SUFFIX); + } + return false; + } + + public int getListId() { + return listId; + } + +} diff --git a/main/src/cgeo/geocaching/ICache.java b/main/src/cgeo/geocaching/ICache.java deleted file mode 100644 index b99d877..0000000 --- a/main/src/cgeo/geocaching/ICache.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * - */ -package cgeo.geocaching; - -import cgeo.geocaching.enumerations.CacheSize; -import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LogType; - -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * Basic interface for caches - */ -public interface ICache extends ILogable, ICoordinates { - - /** - * @return Displayed owner, might differ from the real owner - */ - public String getOwnerDisplayName(); - - /** - * @return GC username of the (actual) owner, might differ from the owner. Never empty. - */ - public String getOwnerUserId(); - - /** - * @return true if the user is the owner of the cache, false else - */ - public boolean isOwner(); - - /** - * @return true is the cache is archived, false else - */ - public boolean isArchived(); - - /** - * @return true is the cache is a Premium Member cache only, false else - */ - public boolean isPremiumMembersOnly(); - - /** - * @return Decrypted hint - */ - public String getHint(); - - /** - * @return Description - */ - public String getDescription(); - - /** - * @return Short Description - */ - public String getShortDescription(); - - - /** - * @return Id - */ - public String getCacheId(); - - /** - * @return Guid - */ - public String getGuid(); - - /** - * @return Location - */ - public String getLocation(); - - /** - * @return Personal note - */ - public String getPersonalNote(); - - - /** - * @return true if the user gave a favorite point to the cache - * - */ - public boolean isFavorite(); - - /** - * @return number of favorite points - * - */ - public int getFavoritePoints(); - - /** - * @return true if the cache is on the watchlist of the user - * - */ - public boolean isOnWatchlist(); - - /** - * @return The date the cache has been hidden - * - */ - public Date getHiddenDate(); - - /** - * null safe list of attributes - * - * @return the list of attributes for this cache - */ - public List<String> getAttributes(); - - /** - * @return the list of trackables in this cache - */ - public List<Trackable> getInventory(); - - /** - * @return the list of spoiler images - */ - public List<Image> getSpoilers(); - - /** - * @return a statistic how often the caches has been found, disabled, archived etc. - */ - public Map<LogType, Integer> getLogCounts(); - - /** - * get the name for lexicographical sorting. - * - * @return normalized, cached name which sort also correct for numerical parts in the name - */ - public String getNameForSorting(); - - /** - * @return Tradi, multi etc. - */ - CacheType getType(); - - /** - * @return Micro, small etc. - */ - CacheSize getSize(); - - /** - * @return true if the user already found the cache - * - */ - boolean isFound(); - - /** - * @return true if the cache is disabled, false else - */ - boolean isDisabled(); - - /** - * @return Difficulty assessment - */ - float getDifficulty(); - - /** - * @return Terrain assessment - */ - float getTerrain(); -} diff --git a/main/src/cgeo/geocaching/ICoordinates.java b/main/src/cgeo/geocaching/ICoordinates.java index b70e4ac..8f78e00 100644 --- a/main/src/cgeo/geocaching/ICoordinates.java +++ b/main/src/cgeo/geocaching/ICoordinates.java @@ -1,6 +1,6 @@ package cgeo.geocaching; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; public interface ICoordinates { diff --git a/main/src/cgeo/geocaching/Image.java b/main/src/cgeo/geocaching/Image.java index f592fc1..5c0e4f0 100644 --- a/main/src/cgeo/geocaching/Image.java +++ b/main/src/cgeo/geocaching/Image.java @@ -31,7 +31,7 @@ public class Image implements Parcelable { } public Image(final File file) { - this("file://" + file.getAbsolutePath(), file.getName(), null); + this(FileUtils.fileToUrl(file), file.getName(), null); } public Image(final Parcel in) { @@ -46,7 +46,7 @@ public class Image implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(final Parcel dest, final int flags) { dest.writeString(url); dest.writeString(title); dest.writeString(description); @@ -54,12 +54,12 @@ public class Image implements Parcelable { public static final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() { @Override - public Image createFromParcel(Parcel in) { + public Image createFromParcel(final Parcel in) { return new Image(in); } @Override - public Image[] newArray(int size) { + public Image[] newArray(final int size) { return new Image[size]; } }; diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java index a64b4cf..9d1c1e0 100644 --- a/main/src/cgeo/geocaching/ImageSelectActivity.java +++ b/main/src/cgeo/geocaching/ImageSelectActivity.java @@ -18,6 +18,7 @@ import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; +import android.os.AsyncTask; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; @@ -48,11 +49,6 @@ public class ImageSelectActivity extends AbstractActionBarActivity { @InjectView(R.id.cancel) protected Button clearButton; @InjectView(R.id.image_preview) protected ImageView imagePreview; - static final String EXTRAS_CAPTION = "caption"; - static final String EXTRAS_DESCRIPTION = "description"; - static final String EXTRAS_URI_AS_STRING = "uri"; - static final String EXTRAS_SCALE = "scale"; - private static final String SAVED_STATE_IMAGE_CAPTION = "cgeo.geocaching.saved_state_image_caption"; private static final String SAVED_STATE_IMAGE_DESCRIPTION = "cgeo.geocaching.saved_state_image_description"; private static final String SAVED_STATE_IMAGE_URI = "cgeo.geocaching.saved_state_image_uri"; @@ -80,10 +76,10 @@ public class ImageSelectActivity extends AbstractActionBarActivity { // Get parameters from intent and basic cache information from database final Bundle extras = getIntent().getExtras(); if (extras != null) { - imageCaption = extras.getString(EXTRAS_CAPTION); - imageDescription = extras.getString(EXTRAS_DESCRIPTION); - imageUri = Uri.parse(extras.getString(EXTRAS_URI_AS_STRING)); - scaleChoiceIndex = extras.getInt(EXTRAS_SCALE, scaleChoiceIndex); + imageCaption = extras.getString(Intents.EXTRA_CAPTION); + imageDescription = extras.getString(Intents.EXTRA_DESCRIPTION); + imageUri = Uri.parse(extras.getString(Intents.EXTRA_URI_AS_STRING)); + scaleChoiceIndex = extras.getInt(Intents.EXTRA_SCALE, scaleChoiceIndex); } // Restore previous state @@ -97,7 +93,7 @@ public class ImageSelectActivity extends AbstractActionBarActivity { cameraButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(final View view) { selectImageFromCamera(); } }); @@ -105,7 +101,7 @@ public class ImageSelectActivity extends AbstractActionBarActivity { storedButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(final View view) { selectImageFromStorage(); } }); @@ -123,20 +119,20 @@ public class ImageSelectActivity extends AbstractActionBarActivity { scaleView.setSelection(scaleChoiceIndex); scaleView.setOnItemSelectedListener(new OnItemSelectedListener() { @Override - public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { + public void onItemSelected(final AdapterView<?> arg0, final View arg1, final int arg2, final long arg3) { scaleChoiceIndex = scaleView.getSelectedItemPosition(); Settings.setLogImageScale(scaleChoiceIndex); } @Override - public void onNothingSelected(AdapterView<?> arg0) { + public void onNothingSelected(final AdapterView<?> arg0) { } }); saveButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v) { + public void onClick(final View v) { saveImageInfo(true); } }); @@ -144,7 +140,7 @@ public class ImageSelectActivity extends AbstractActionBarActivity { clearButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v) { + public void onClick(final View v) { saveImageInfo(false); } }); @@ -162,27 +158,36 @@ public class ImageSelectActivity extends AbstractActionBarActivity { outState.putInt(SAVED_STATE_IMAGE_SCALE, scaleChoiceIndex); } - public void saveImageInfo(boolean saveInfo) { + public void saveImageInfo(final boolean saveInfo) { if (saveInfo) { - final String filename = writeScaledImage(imageUri.getPath()); - if (filename != null) { - imageUri = Uri.parse(filename); - final Intent intent = new Intent(); - syncEditTexts(); - intent.putExtra(EXTRAS_CAPTION, imageCaption); - intent.putExtra(EXTRAS_DESCRIPTION, imageDescription); - intent.putExtra(EXTRAS_URI_AS_STRING, imageUri.toString()); - intent.putExtra(EXTRAS_SCALE, scaleChoiceIndex); - setResult(RESULT_OK, intent); - } else { - showToast(res.getString(R.string.err_select_logimage_failed)); - setResult(RESULT_CANCELED); - } + new AsyncTask<Void, Void, String>() { + @Override + protected String doInBackground(final Void... params) { + return writeScaledImage(imageUri.getPath()); + } + + @Override + protected void onPostExecute(final String filename) { + if (filename != null) { + imageUri = Uri.parse(filename); + final Intent intent = new Intent(); + syncEditTexts(); + intent.putExtra(Intents.EXTRA_CAPTION, imageCaption); + intent.putExtra(Intents.EXTRA_DESCRIPTION, imageDescription); + intent.putExtra(Intents.EXTRA_URI_AS_STRING, imageUri.toString()); + intent.putExtra(Intents.EXTRA_SCALE, scaleChoiceIndex); + setResult(RESULT_OK, intent); + } else { + showToast(res.getString(R.string.err_select_logimage_failed)); + setResult(RESULT_CANCELED); + } + finish(); + } + }.execute(); } else { setResult(RESULT_CANCELED); + finish(); } - - finish(); } private void syncEditTexts() { @@ -193,7 +198,7 @@ public class ImageSelectActivity extends AbstractActionBarActivity { private void selectImageFromCamera() { // create Intent to take a picture and return control to the calling application - Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); imageUri = ImageUtils.getOutputImageFileUri(); // create a file to save the image if (imageUri == null) { @@ -207,14 +212,14 @@ public class ImageSelectActivity extends AbstractActionBarActivity { } private void selectImageFromStorage() { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/jpeg"); startActivityForResult(Intent.createChooser(intent, "Select Image"), SELECT_STORED_IMAGE); } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (resultCode == RESULT_CANCELED) { // User cancelled the image capture showToast(getResources().getString(R.string.info_select_logimage_cancelled)); @@ -232,7 +237,7 @@ public class ImageSelectActivity extends AbstractActionBarActivity { if (data != null) { final Uri selectedImage = data.getData(); if (Build.VERSION.SDK_INT < VERSION_CODES.KITKAT) { - String[] filePathColumn = { MediaColumns.DATA }; + final String[] filePathColumn = { MediaColumns.DATA }; Cursor cursor = null; try { @@ -243,14 +248,14 @@ public class ImageSelectActivity extends AbstractActionBarActivity { } cursor.moveToFirst(); - int columnIndex = cursor.getColumnIndex(filePathColumn[0]); - String filePath = cursor.getString(columnIndex); + final int columnIndex = cursor.getColumnIndex(filePathColumn[0]); + final String filePath = cursor.getString(columnIndex); if (StringUtils.isBlank(filePath)) { showFailure(); return; } imageUri = Uri.parse(filePath); - } catch (Exception e) { + } catch (final Exception e) { Log.e("ImageSelectActivity.onActivityResult", e); showFailure(); } finally { @@ -269,7 +274,7 @@ public class ImageSelectActivity extends AbstractActionBarActivity { output = new FileOutputStream(outputFile); LocalStorage.copy(input, output); imageUri = Uri.fromFile(outputFile); - } catch (FileNotFoundException e) { + } catch (final FileNotFoundException e) { Log.e("ImageSelectActivity.onStartResult", e); } finally { IOUtils.closeQuietly(input); @@ -288,7 +293,6 @@ public class ImageSelectActivity extends AbstractActionBarActivity { /** * Scales and writes the scaled image. * - * @param filePath * @return the scaled image path, or <tt>null</tt> if the image cannot be decoded */ @Nullable @@ -314,8 +318,17 @@ public class ImageSelectActivity extends AbstractActionBarActivity { return; } - final Bitmap bitmap = ImageUtils.readAndScaleImageToFitDisplay(imageUri.getPath()); - imagePreview.setImageBitmap(bitmap); - imagePreview.setVisibility(View.VISIBLE); + new AsyncTask<Void, Void, Bitmap>() { + @Override + protected Bitmap doInBackground(final Void... params) { + return ImageUtils.readAndScaleImageToFitDisplay(imageUri.getPath()); + } + + @Override + protected void onPostExecute(final Bitmap bitmap) { + imagePreview.setImageBitmap(bitmap); + imagePreview.setVisibility(View.VISIBLE); + } + }.execute(); } } diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java index b75e5eb..975a720 100644 --- a/main/src/cgeo/geocaching/ImagesActivity.java +++ b/main/src/cgeo/geocaching/ImagesActivity.java @@ -6,6 +6,7 @@ import cgeo.geocaching.ui.ImagesList; import cgeo.geocaching.ui.ImagesList.ImageType; import org.apache.commons.collections4.CollectionUtils; + import rx.Subscription; import android.content.Context; @@ -28,7 +29,7 @@ public class ImagesActivity extends AbstractActionBarActivity { private Subscription subscription; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // get parameters @@ -78,11 +79,12 @@ public class ImagesActivity extends AbstractActionBarActivity { super.onStop(); } - public static void startActivityLogImages(final Context fromActivity, final String geocode, List<Image> logImages) { + public static void startActivityLogImages(final Context fromActivity, final String geocode, final List<Image> logImages) { startActivity(fromActivity, geocode, logImages, ImageType.LogImages); } - private static void startActivity(final Context fromActivity, final String geocode, List<Image> logImages, ImageType imageType) { + @SuppressWarnings("deprecation") + private static void startActivity(final Context fromActivity, final String geocode, final List<Image> logImages, final ImageType imageType) { final Intent logImgIntent = new Intent(fromActivity, ImagesActivity.class); // if resuming our app within this activity, finish it and return to the cache activity logImgIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) @@ -95,18 +97,18 @@ public class ImagesActivity extends AbstractActionBarActivity { fromActivity.startActivity(logImgIntent); } - public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<Image> spoilers) { + public static void startActivitySpoilerImages(final Context fromActivity, final String geocode, final List<Image> spoilers) { startActivity(fromActivity, geocode, spoilers, ImageType.SpoilerImages); } @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); imagesList.onCreateContextMenu(menu, v); } @Override - public boolean onContextItemSelected(MenuItem item) { + public boolean onContextItemSelected(final MenuItem item) { if (imagesList.onContextItemSelected(item)) { return true; } diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java index a55c22a..cbf2346 100644 --- a/main/src/cgeo/geocaching/Intents.java +++ b/main/src/cgeo/geocaching/Intents.java @@ -1,5 +1,13 @@ package cgeo.geocaching; +import cgeo.geocaching.enumerations.CacheListType; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; + +import android.content.Intent; +import android.os.Bundle; + public class Intents { private Intents() { @@ -10,6 +18,8 @@ public class Intents { public static final String EXTRA_ADDRESS = PREFIX + "address"; public static final String EXTRA_COORDS = PREFIX + "coords"; + public static final String EXTRA_LATITUDE = PREFIX + "latitude"; + public static final String EXTRA_LONGITUDE = PREFIX + "longitude"; public static final String EXTRA_COUNT = PREFIX + "count"; public static final String EXTRA_GEOCODE = PREFIX + "geocode"; public static final String EXTRA_GUID = PREFIX + "guid"; @@ -18,7 +28,24 @@ public class Intents { public static final String EXTRA_KEYWORD = PREFIX + "keyword"; public static final String EXTRA_KEYWORD_SEARCH = PREFIX + "keyword_search"; public static final String EXTRA_LIST_ID = PREFIX + "list_id"; - public static final String EXTRA_LIST_TYPE = PREFIX + "list_type"; + public static final String EXTRA_CAPTION = PREFIX + "caption"; + public static final String EXTRA_DESCRIPTION = PREFIX + "description"; + public static final String EXTRA_URI_AS_STRING = PREFIX + "uri"; + public static final String EXTRA_SCALE = PREFIX + "scale"; + + public static final String EXTRA_WPTTYPE = PREFIX + "wpttype"; + public static final String EXTRA_MAPSTATE = PREFIX + "mapstate"; + public static final String EXTRA_TITLE = PREFIX + "title"; + public static final String EXTRA_MAP_MODE = PREFIX + "mapMode"; + public static final String EXTRA_LIVE_ENABLED = PREFIX + "liveEnabled"; + + public static final String EXTRA_DOWNLOAD = PREFIX + "download"; + + /** + * list type to be used with the cache list activity. Be aware to use the String representation of the corresponding + * enum. + */ + private static final String EXTRA_LIST_TYPE = PREFIX + "list_type"; public static final String EXTRA_MAP_FILE = PREFIX + "map_file"; public static final String EXTRA_NAME = PREFIX + "name"; public static final String EXTRA_SEARCH = PREFIX + "search"; @@ -49,4 +76,25 @@ public class Intents { public static final String EXTRA_OAUTH_TEMP_TOKEN_SECRET_PREF = PREFIX_OAUTH + "tempSecretPref"; public static final String EXTRA_OAUTH_TOKEN_PUBLIC_KEY = PREFIX_OAUTH + "publicTokenPref"; public static final String EXTRA_OAUTH_TOKEN_SECRET_KEY = PREFIX_OAUTH + "secretTokenPref"; + + public static Intent putListType(final Intent intent, final @NonNull CacheListType listType) { + intent.putExtra(Intents.EXTRA_LIST_TYPE, listType.name()); + return intent; + } + + public static @NonNull CacheListType getListType(final Intent intent) { + final Bundle extras = intent.getExtras(); + if (extras == null) { + return CacheListType.OFFLINE; + } + final String typeName = extras.getString(Intents.EXTRA_LIST_TYPE); + if (StringUtils.isBlank(typeName)) { + return CacheListType.OFFLINE; + } + try { + return CacheListType.valueOf(typeName); + } catch (final IllegalArgumentException ignored) { + return CacheListType.OFFLINE; + } + } } diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java index bc87525..6fbd7bf 100644 --- a/main/src/cgeo/geocaching/LogCacheActivity.java +++ b/main/src/cgeo/geocaching/LogCacheActivity.java @@ -1,6 +1,7 @@ package cgeo.geocaching; import butterknife.ButterKnife; +import butterknife.InjectView; import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.connector.ILoggingManager; @@ -11,12 +12,14 @@ import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.LogTypeTrackable; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.gcvote.GCVote; +import cgeo.geocaching.gcvote.GCVoteRatingBarUtil; +import cgeo.geocaching.gcvote.GCVoteRatingBarUtil.OnRatingChangeListener; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.dialog.DateDialog; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.AsyncTaskWithProgress; -import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; @@ -44,8 +47,6 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.LinearLayout; -import android.widget.RatingBar; -import android.widget.RatingBar.OnRatingBarChangeListener; import android.widget.TextView; import java.util.ArrayList; @@ -54,8 +55,6 @@ import java.util.Date; import java.util.List; public class LogCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent { - static final String EXTRAS_GEOCODE = "geocode"; - static final String EXTRAS_ID = "id"; private static final String SAVED_STATE_RATING = "cgeo.geocaching.saved_state_rating"; private static final String SAVED_STATE_TYPE = "cgeo.geocaching.saved_state_type"; @@ -72,9 +71,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private String text = null; private List<LogType> possibleLogTypes = new ArrayList<>(); private List<TrackableLog> trackables = null; - private CheckBox tweetCheck = null; - private LinearLayout tweetBox = null; - private LinearLayout logPasswordBox = null; + protected @InjectView(R.id.tweet) CheckBox tweetCheck; + protected @InjectView(R.id.tweet_box) LinearLayout tweetBox; + protected @InjectView(R.id.log_password_box) LinearLayout logPasswordBox; private SparseArray<TrackableLog> actionButtons; private ILoggingManager loggingManager; @@ -88,9 +87,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private Uri imageUri; private boolean sendButtonEnabled; - public void onLoadFinished() { - if (loggingManager.hasLoaderError()) { showErrorLoadingData(); return; @@ -111,6 +108,8 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia showToast(res.getString(R.string.info_log_type_changed)); } + initializeRatingBar(); + enablePostButton(true); initializeTrackablesAction(); @@ -141,7 +140,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } actionButtons = new SparseArray<>(); - final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory); + final LinearLayout inventoryView = ButterKnife.findById(this, R.id.inventory); inventoryView.removeAllViews(); for (final TrackableLog tb : trackables) { @@ -165,7 +164,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia final String tbCode = tb.trackCode; inventoryItem.setClickable(true); - inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() { + ButterKnife.findById(inventoryItem, R.id.info).setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { @@ -179,10 +178,10 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } if (inventoryView.getChildCount() > 0) { - findViewById(R.id.inventory_box).setVisibility(View.VISIBLE); + ButterKnife.findById(this, R.id.inventory_box).setVisibility(View.VISIBLE); } if (inventoryView.getChildCount() > 1) { - final LinearLayout inventoryChangeAllView = (LinearLayout) findViewById(R.id.inventory_changeall); + final LinearLayout inventoryChangeAllView = ButterKnife.findById(this, R.id.inventory_changeall); final Button changeButton = ButterKnife.findById(inventoryChangeAllView, R.id.changebutton); changeButton.setOnClickListener(new View.OnClickListener() { @@ -208,9 +207,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia // Get parameters from intent and basic cache information from database final Bundle extras = getIntent().getExtras(); if (extras != null) { - geocode = extras.getString(EXTRAS_GEOCODE); + geocode = extras.getString(Intents.EXTRA_GEOCODE); if (StringUtils.isBlank(geocode)) { - final String cacheid = extras.getString(EXTRAS_ID); + final String cacheid = extras.getString(Intents.EXTRA_ID); if (StringUtils.isNotBlank(cacheid)) { geocode = DataStore.getGeocodeForGuid(cacheid); } @@ -227,13 +226,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia setTitle(res.getString(R.string.log_new_log) + ": " + cache.getGeocode()); } - // Get ids for later use - tweetBox = (LinearLayout) findViewById(R.id.tweet_box); - tweetCheck = (CheckBox) findViewById(R.id.tweet); - logPasswordBox = (LinearLayout) findViewById(R.id.log_password_box); - - final RatingBar ratingBar = (RatingBar) findViewById(R.id.gcvoteRating); - initializeRatingBar(ratingBar); + initializeRatingBar(); // initialize with default values setDefaultValues(); @@ -261,7 +254,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } enablePostButton(false); - final Button typeButton = (Button) findViewById(R.id.type); + final Button typeButton = ButterKnife.findById(this, R.id.type); typeButton.setText(typeSelected.getL10n()); typeButton.setOnClickListener(new View.OnClickListener() { @@ -271,11 +264,11 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } }); - final Button dateButton = (Button) findViewById(R.id.date); + final Button dateButton = ButterKnife.findById(this, R.id.date); setDate(date); dateButton.setOnClickListener(new DateListener()); - final EditText logView = (EditText) findViewById(R.id.log); + final EditText logView = ButterKnife.findById(this, R.id.log); if (StringUtils.isBlank(currentLogText()) && StringUtils.isNotBlank(text)) { logView.setText(text); Dialogs.moveCursorToEnd(logView); @@ -288,27 +281,19 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia loggingManager = cache.getLoggingManager(this); loggingManager.init(); + requestKeyboardForLogging(); } - private void initializeRatingBar(final RatingBar ratingBar) { - final TextView label = (TextView) findViewById(R.id.gcvoteLabel); + private void initializeRatingBar() { if (GCVote.isVotingPossible(cache)) { - ratingBar.setVisibility(View.VISIBLE); - label.setVisibility(View.VISIBLE); - } - ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { + GCVoteRatingBarUtil.initializeRatingBar(cache, getWindow().getDecorView().getRootView(), new OnRatingChangeListener() { - @Override - public void onRatingChanged(final RatingBar ratingBar, final float stars, final boolean fromUser) { - // 0.5 is not a valid rating, therefore we must limit - rating = GCVote.isValidRating(stars) ? stars : 0; - if (rating < stars) { - ratingBar.setRating(rating); + @Override + public void onRatingChanged(final float stars) { + rating = stars; } - label.setText(GCVote.getDescription(rating)); - } - }); - ratingBar.setRating(cache.getMyVote()); + }); + } } private void setDefaultValues() { @@ -316,7 +301,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia rating = GCVote.NO_RATING; typeSelected = cache.getDefaultLogType(); // it this is an attended event log, use the event date by default instead of the current date - if (cache.isEventCache() && DateUtils.isPastEvent(cache) && typeSelected == LogType.ATTENDED) { + if (cache.isEventCache() && CalendarUtils.isPastEvent(cache) && typeSelected == LogType.ATTENDED) { date.setTime(cache.getHiddenDate()); } text = null; @@ -333,9 +318,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia setType(typeSelected); setDate(date); - final EditText logView = (EditText) findViewById(R.id.log); + final EditText logView = ButterKnife.findById(this, R.id.log); logView.setText(StringUtils.EMPTY); - final EditText logPasswordView = (EditText) findViewById(R.id.log_password); + final EditText logPasswordView = ButterKnife.findById(this, R.id.log_password); logPasswordView.setText(StringUtils.EMPTY); showToast(res.getString(R.string.info_log_cleared)); @@ -368,12 +353,12 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia public void setDate(final Calendar dateIn) { date = dateIn; - final Button dateButton = (Button) findViewById(R.id.date); + final Button dateButton = ButterKnife.findById(this, R.id.date); dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime())); } public void setType(final LogType type) { - final Button typeButton = (Button) findViewById(R.id.type); + final Button typeButton = ButterKnife.findById(this, R.id.type); typeSelected = type; typeButton.setText(typeSelected.getL10n()); @@ -419,13 +404,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia final String log = logTexts[0]; final String logPwd = logTexts.length > 1 ? logTexts[1] : null; try { - final LogResult logResult = loggingManager.postLog(cache, typeSelected, date, log, logPwd, trackables); + final LogResult logResult = loggingManager.postLog(typeSelected, date, log, logPwd, trackables); if (logResult.getPostLogResult() == StatusCode.NO_ERROR) { // update geocache in DB - if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED || typeSelected == LogType.WEBCAM_PHOTO_TAKEN) { + if (typeSelected.isFoundLog()) { cache.setFound(true); - cache.setVisitedDate(new Date().getTime()); + cache.setVisitedDate(date.getTimeInMillis()); } DataStore.saveChangedCache(cache); @@ -434,7 +419,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia final LogEntry logNow = new LogEntry(date.getTimeInMillis(), typeSelected, log); logNow.friend = true; newLogs.add(0, logNow); - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), newLogs); + DataStore.saveLogs(cache.getGeocode(), newLogs); // update offline log in DB cache.clearOfflineLog(); @@ -444,8 +429,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia Twitter.postTweetCache(geocode, logNow); } } - if (GCVote.isValidRating(rating)) { - GCVote.setRating(cache, rating); + if (GCVote.isValidRating(rating) && GCVote.isVotingPossible(cache)) { + if (GCVote.setRating(cache, rating)) { + cache.setMyVote(rating); + DataStore.saveChangedCache(cache); + } else { + showToast(res.getString(R.string.err_gcvote_send_rating)); + } } if (StringUtils.isNotBlank(imageUri.getPath())) { @@ -453,7 +443,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia final String uploadedImageUrl = imageResult.getImageUri(); if (StringUtils.isNotEmpty(uploadedImageUrl)) { logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription)); - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), newLogs); + DataStore.saveLogs(cache.getGeocode(), newLogs); } return imageResult.getPostResult(); } @@ -461,7 +451,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia return logResult.getPostLogResult(); } catch (final RuntimeException e) { - Log.e("VisitCacheActivity.Poster.doInBackgroundInternal", e); + Log.e("LogCacheActivity.Poster.doInBackgroundInternal", e); } return StatusCode.LOG_POST_ERROR; @@ -491,16 +481,17 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia // again will be easy using "Clear" while retyping the text may not be. if (force || (StringUtils.isNotEmpty(log) && !StringUtils.equals(log, text))) { cache.logOffline(this, log, date, typeSelected); + Settings.setLastCacheLog(log); } text = log; } private String currentLogText() { - return ((EditText) findViewById(R.id.log)).getText().toString(); + return ButterKnife.<EditText>findById(this, R.id.log).getText().toString(); } private String currentLogPassword() { - return ((EditText) findViewById(R.id.log_password)).getText().toString(); + return ButterKnife.<EditText>findById(this, R.id.log_password).getText().toString(); } @Override @@ -578,9 +569,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private void selectImage() { final Intent selectImageIntent = new Intent(this, ImageSelectActivity.class); - selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_CAPTION, imageCaption); - selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_DESCRIPTION, imageDescription); - selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_URI_AS_STRING, imageUri.toString()); + selectImageIntent.putExtra(Intents.EXTRA_CAPTION, imageCaption); + selectImageIntent.putExtra(Intents.EXTRA_DESCRIPTION, imageDescription); + selectImageIntent.putExtra(Intents.EXTRA_URI_AS_STRING, imageUri.toString()); startActivityForResult(selectImageIntent, SELECT_IMAGE); } @@ -589,9 +580,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (requestCode == SELECT_IMAGE) { if (resultCode == RESULT_OK) { - imageCaption = data.getStringExtra(ImageSelectActivity.EXTRAS_CAPTION); - imageDescription = data.getStringExtra(ImageSelectActivity.EXTRAS_DESCRIPTION); - imageUri = Uri.parse(data.getStringExtra(ImageSelectActivity.EXTRAS_URI_AS_STRING)); + imageCaption = data.getStringExtra(Intents.EXTRA_CAPTION); + imageDescription = data.getStringExtra(Intents.EXTRA_DESCRIPTION); + imageUri = Uri.parse(data.getStringExtra(Intents.EXTRA_URI_AS_STRING)); } else if (resultCode != RESULT_CANCELED) { // Image capture failed, advise user showToast(getResources().getString(R.string.err_select_logimage_failed)); @@ -603,7 +594,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case R.id.menu_send: - sendLog(); + sendLogAndConfirm(); return true; case R.id.menu_image: selectImage(); @@ -622,18 +613,37 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia return super.onOptionsItemSelected(item); } - private void sendLog() { + private void sendLogAndConfirm() { if (!sendButtonEnabled) { Dialogs.message(this, R.string.log_post_not_possible); + return; + } + if (CalendarUtils.isFuture(date)) { + Dialogs.message(this, R.string.log_date_future_not_allowed); + return; + } + if (typeSelected.mustConfirmLog()) { + Dialogs.confirm(this, R.string.confirm_log_title, res.getString(R.string.confirm_log_message, typeSelected.getL10n()), new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + sendLogInternal(); + } + }); } else { - final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ? - R.string.log_saving : - R.string.log_saving_and_uploading); - new Poster(this, message).execute(currentLogText(), currentLogPassword()); + sendLogInternal(); } } + private void sendLogInternal() { + final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ? + R.string.log_saving : + R.string.log_saving_and_uploading); + new Poster(this, message).execute(currentLogText(), currentLogPassword()); + Settings.setLastCacheLog(currentLogText()); + } + @Override public boolean onCreateOptionsMenu(final Menu menu) { super.onCreateOptionsMenu(menu); @@ -650,4 +660,16 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia .setTarget(new ActionItemTarget(this, R.id.menu_send)) .setContent(R.string.showcase_logcache_title, R.string.showcase_logcache_text); } + + public static Intent getLogCacheIntent(final Activity context, final String cacheId, final String geocode) { + final Intent logVisitIntent = new Intent(context, LogCacheActivity.class); + logVisitIntent.putExtra(Intents.EXTRA_ID, cacheId); + logVisitIntent.putExtra(Intents.EXTRA_GEOCODE, geocode); + return logVisitIntent; + } + + @Override + protected String getLastLog() { + return Settings.getLastCacheLog(); + } } diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java index b4b346c..41c222b 100644 --- a/main/src/cgeo/geocaching/LogEntry.java +++ b/main/src/cgeo/geocaching/LogEntry.java @@ -2,7 +2,6 @@ package cgeo.geocaching; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.settings.Settings; -import cgeo.geocaching.utils.DateUtils; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.MatcherWrapper; @@ -89,7 +88,7 @@ public final class LogEntry { public CharSequence getImageTitles() { final List<String> titles = new ArrayList<>(5); - for (Image image : getLogImages()) { + for (final Image image : getLogImages()) { if (StringUtils.isNotBlank(image.getTitle())) { titles.add(HtmlUtils.extractText(image.getTitle())); } @@ -100,16 +99,12 @@ public final class LogEntry { return StringUtils.join(titles, ", "); } - public int daysSinceLog() { - return DateUtils.daysSince(date); - } - /** * Get the log text to be displayed. Depending on the settings, color tags might be removed. */ public String getDisplayText() { if (Settings.getPlainLogs()) { - MatcherWrapper matcher = new MatcherWrapper(PATTERN_REMOVE_COLORS, log); + final MatcherWrapper matcher = new MatcherWrapper(PATTERN_REMOVE_COLORS, log); return matcher.replaceAll(StringUtils.EMPTY); } return log; diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java index 26f7c84..fa77458 100644 --- a/main/src/cgeo/geocaching/LogTrackableActivity.java +++ b/main/src/cgeo/geocaching/LogTrackableActivity.java @@ -3,6 +3,7 @@ package cgeo.geocaching; import butterknife.ButterKnife; import butterknife.InjectView; +import cgeo.geocaching.activity.Keyboard; import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.enumerations.LogType; @@ -15,7 +16,9 @@ import cgeo.geocaching.ui.dialog.DateDialog; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; +import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -28,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.ContextMenu; +import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; @@ -61,6 +65,8 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat private int attempts = 0; private Trackable trackable; + final public static int LOG_TRACKABLE = 1; + private final Handler showProgressHandler = new Handler() { @Override public void handleMessage(final Message msg) { @@ -106,6 +112,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat final StatusCode error = (StatusCode) msg.obj; if (error == StatusCode.NO_ERROR) { showToast(res.getString(R.string.info_log_posted)); + setResult(RESULT_OK); finish(); } else { showToast(error.getErrorString(res)); @@ -132,20 +139,31 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat trackable = DataStore.loadTrackable(geocode); + if (trackable == null) { + Log.e("LogTrackableActivity.onCreate: cannot load trackable " + geocode); + setResult(RESULT_CANCELED); + finish(); + return; + } + if (StringUtils.isNotBlank(trackable.getName())) { setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getName()); } else { setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getGeocode()); } - if (guid == null) { - showToast(res.getString(R.string.err_tb_forgot_saw)); + init(); + requestKeyboardForLogging(); + } - finish(); - return; + @Override + protected void requestKeyboardForLogging() { + if (StringUtils.isBlank(trackingEditText.getText())) { + new Keyboard(this).show(trackingEditText); + } + else { + super.requestKeyboardForLogging(); } - - init(); } @Override @@ -241,11 +259,6 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat public LoadDataThread() { super("Load data for logging trackable"); - if (guid == null) { - showToast(res.getString(R.string.err_tb_forgot_saw)); - - finish(); - } } @Override @@ -309,6 +322,9 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) { Twitter.postTweetTrackable(geocode, new LogEntry(0, typeSelected, log)); } + if (status == StatusCode.NO_ERROR) { + addLocalTrackableLog(log); + } return status; } catch (final Exception e) { @@ -318,12 +334,25 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat return StatusCode.LOG_POST_ERROR; } - public static void startActivity(final Context context, final Trackable trackable) { + /** + * Adds the new log to the list of log entries for this trackable to be able to show it in the trackable activity. + * + * + */ + private void addLocalTrackableLog(final String logText) { + final LogEntry logEntry = new LogEntry(date.getTimeInMillis(), typeSelected, logText); + final ArrayList<LogEntry> modifiedLogs = new ArrayList<>(trackable.getLogs()); + modifiedLogs.add(0, logEntry); + trackable.setLogs(modifiedLogs); + DataStore.saveTrackable(trackable); + } + + public static Intent getIntent(final Context context, final Trackable trackable) { final Intent logTouchIntent = new Intent(context, LogTrackableActivity.class); logTouchIntent.putExtra(Intents.EXTRA_GEOCODE, trackable.getGeocode()); logTouchIntent.putExtra(Intents.EXTRA_GUID, trackable.getGuid()); logTouchIntent.putExtra(Intents.EXTRA_TRACKING_CODE, trackable.getTrackingcode()); - context.startActivity(logTouchIntent); + return logTouchIntent; } @Override @@ -355,9 +384,26 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat final String tracking = trackingEditText.getText().toString(); final String log = logEditText.getText().toString(); new PostLogThread(postLogHandler, tracking, log).start(); + Settings.setLastTrackableLog(log); } else { showToast(res.getString(R.string.err_log_load_data_still)); } } + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + final boolean result = super.onCreateOptionsMenu(menu); + for (final LogTemplate template : LogTemplateProvider.getTemplatesWithoutSignature()) { + if (template.getTemplateString().equals("NUMBER")) { + menu.findItem(R.id.menu_templates).getSubMenu().removeItem(template.getItemId()); + } + } + return result; + } + + @Override + protected String getLastLog() { + return Settings.getLastTrackableLog(); + } + } diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index c0c6712..45ce698 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -7,17 +7,21 @@ import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.capability.ILogin; -import cgeo.geocaching.connector.gc.GCConnector; -import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; import cgeo.geocaching.list.PseudoList; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.AndroidGeocoder; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.MapQuestGeocoder; +import cgeo.geocaching.location.Units; import cgeo.geocaching.maps.CGeoMap; +import cgeo.geocaching.network.Network; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.GpsStatusProvider; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.SettingsActivity; import cgeo.geocaching.ui.dialog.Dialogs; @@ -35,21 +39,23 @@ import com.google.zxing.integration.android.IntentResult; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.Observable.OnSubscribe; -import rx.Subscriber; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; import rx.functions.Action1; -import rx.subscriptions.Subscriptions; +import rx.functions.Func1; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.SearchManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentFilter; import android.content.res.Configuration; import android.location.Address; -import android.location.Geocoder; +import android.net.ConnectivityManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -64,12 +70,12 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Locale; public class MainActivity extends AbstractActionBarActivity { @InjectView(R.id.nav_satellites) protected TextView navSatellites; @@ -88,11 +94,9 @@ public class MainActivity extends AbstractActionBarActivity { public static final int SEARCH_REQUEST_CODE = 2; - private int version = 0; - private boolean cleanupRunning = false; - private int countBubbleCnt = 0; private Geopoint addCoords = null; private boolean initialized = false; + private ConnectivityChangeReceiver connectivityChangeReceiver; private final UpdateLocation locationUpdater = new UpdateLocation(); @@ -110,7 +114,7 @@ public class MainActivity extends AbstractActionBarActivity { for (final ILogin conn : loginConns) { - final TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, null); + final TextView connectorInfo = (TextView) inflater.inflate(R.layout.main_activity_connectorstatus, infoArea, false); infoArea.addView(connectorInfo); final StringBuilder userInfo = new StringBuilder(conn.getName()).append(Formatter.SEPARATOR); @@ -128,6 +132,19 @@ public class MainActivity extends AbstractActionBarActivity { } }; + private final class ConnectivityChangeReceiver extends BroadcastReceiver { + private boolean isConnected = Network.isNetworkConnected(); + + @Override + public void onReceive(final Context context, final Intent intent) { + final boolean wasConnected = isConnected; + isConnected = Network.isNetworkConnected(); + if (isConnected && !wasConnected) { + startBackgroundLogin(); + } + } + } + private static String formatAddress(final Address address) { final ArrayList<String> addressParts = new ArrayList<>(); @@ -147,37 +164,16 @@ public class MainActivity extends AbstractActionBarActivity { return StringUtils.join(addressParts, ", "); } - private class SatellitesHandler extends GeoDirHandler { - - private boolean gpsEnabled = false; - private int satellitesFixed = 0; - private int satellitesVisible = 0; - + private final Action1<GpsStatusProvider.Status> satellitesHandler = new Action1<Status>() { @Override - public void updateGeoData(final IGeoData data) { - if (data.getGpsEnabled() == gpsEnabled && - data.getSatellitesFixed() == satellitesFixed && - data.getSatellitesVisible() == satellitesVisible) { - return; - } - gpsEnabled = data.getGpsEnabled(); - satellitesFixed = data.getSatellitesFixed(); - satellitesVisible = data.getSatellitesVisible(); - - if (gpsEnabled) { - if (satellitesFixed > 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible); - } else if (satellitesVisible >= 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": 0/" + satellitesVisible); - } + public void call(final Status gpsStatus) { + if (gpsStatus.gpsEnabled) { + navSatellites.setText(res.getString(R.string.loc_sat) + ": " + gpsStatus.satellitesFixed + '/' + gpsStatus.satellitesVisible); } else { navSatellites.setText(res.getString(R.string.loc_gps_disabled)); } } - - } - - private final SatellitesHandler satellitesHandler = new SatellitesHandler(); + }; private final Handler firstLoginHandler = new Handler() { @@ -214,8 +210,7 @@ public class MainActivity extends AbstractActionBarActivity { setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // type to search - version = Version.getVersionCode(this); - Log.i("Starting " + getPackageName() + ' ' + version + " a.k.a " + Version.getVersionName(this)); + Log.i("Starting " + getPackageName() + ' ' + Version.getVersionCode(this) + " a.k.a " + Version.getVersionName(this)); init(); @@ -231,30 +226,34 @@ public class MainActivity extends AbstractActionBarActivity { @Override public void onResume() { - super.onResume(Subscriptions.from(locationUpdater.start(GeoDirHandler.UPDATE_GEODATA), satellitesHandler.start(GeoDirHandler.UPDATE_GEODATA))); + super.onResume(locationUpdater.start(GeoDirHandler.UPDATE_GEODATA | GeoDirHandler.LOW_POWER), + Sensors.getInstance().gpsStatusObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(satellitesHandler)); updateUserInfoHandler.sendEmptyMessage(-1); startBackgroundLogin(); init(); + + connectivityChangeReceiver = new ConnectivityChangeReceiver(); + registerReceiver(connectivityChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); } private void startBackgroundLogin() { - assert(app != null); + assert app != null; final boolean mustLogin = app.mustRelog(); for (final ILogin conn : ConnectorFactory.getActiveLiveConnectors()) { if (mustLogin || !conn.isLoggedIn()) { - new Thread() { + RxUtils.networkScheduler.createWorker().schedule(new Action0() { @Override - public void run() { - if (mustLogin && conn == GCConnector.getInstance()) { + public void call() { + if (mustLogin) { // Properly log out from geocaching.com - GCLogin.getInstance().logout(); + conn.logout(); } conn.login(firstLoginHandler, MainActivity.this); updateUserInfoHandler.sendEmptyMessage(-1); } - }.start(); + }); } } } @@ -276,6 +275,7 @@ public class MainActivity extends AbstractActionBarActivity { @Override public void onPause() { initialized = false; + unregisterReceiver(connectivityChangeReceiver); super.onPause(); } @@ -315,7 +315,7 @@ public class MainActivity extends AbstractActionBarActivity { startActivity(new Intent(this, SettingsActivity.class)); return true; case R.id.menu_history: - CacheListActivity.startActivityHistory(this); + startActivity(CacheListActivity.getHistoryIntent(this)); return true; case R.id.menu_scan: startScannerApplication(); @@ -447,7 +447,7 @@ public class MainActivity extends AbstractActionBarActivity { setFilterTitle(); checkRestore(); - (new CleanDatabaseThread()).start(); + DataStore.cleanIfNeeded(this); } protected void selectGlobalTypeFilter() { @@ -464,11 +464,11 @@ public class MainActivity extends AbstractActionBarActivity { sorted.addAll(Arrays.asList(CacheType.values())); sorted.removeAll(cacheTypes); + final Collator collator = TextUtils.getCollator(); Collections.sort(sorted, new Comparator<CacheType>() { - @Override public int compare(final CacheType left, final CacheType right) { - return left.getL10n().compareToIgnoreCase(right.getL10n()); + return collator.compare(left.getL10n(), right.getL10n()); } }); @@ -501,7 +501,23 @@ public class MainActivity extends AbstractActionBarActivity { } public void updateCacheCounter() { - (new CountBubbleUpdateThread()).start(); + AppObservable.bindActivity(this, DataStore.getAllCachesCountObservable()).subscribe(new Action1<Integer>() { + @Override + public void call(final Integer countBubbleCnt1) { + if (countBubbleCnt1 == 0) { + countBubble.setVisibility(View.GONE); + } else { + countBubble.setText(Integer.toString(countBubbleCnt1)); + countBubble.bringToFront(); + countBubble.setVisibility(View.VISIBLE); + } + } + }, new Action1<Throwable>() { + @Override + public void call(final Throwable throwable) { + Log.e("Unable to add bubble count", throwable); + } + }); } private void checkRestore() { @@ -534,7 +550,7 @@ public class MainActivity extends AbstractActionBarActivity { private class UpdateLocation extends GeoDirHandler { @Override - public void updateGeoData(final IGeoData geo) { + public void updateGeoData(final GeoData geo) { if (!nearestView.isClickable()) { nearestView.setFocusable(true); nearestView.setClickable(true); @@ -556,29 +572,21 @@ public class MainActivity extends AbstractActionBarActivity { navAccuracy.setText(null); } + final Geopoint currentCoords = geo.getCoords(); if (Settings.isShowAddress()) { if (addCoords == null) { navLocation.setText(R.string.loc_no_addr); } - if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5)) { - final Observable<String> address = Observable.create(new OnSubscribe<String>() { + if (addCoords == null || (currentCoords.distanceTo(addCoords) > 0.5)) { + addCoords = currentCoords; + final Observable<String> address = (new AndroidGeocoder(MainActivity.this).getFromLocation(currentCoords) + .onErrorResumeNext(MapQuestGeocoder.getFromLocation(currentCoords))).map(new Func1<Address, String>() { @Override - public void call(final Subscriber<? super String> subscriber) { - try { - addCoords = geo.getCoords(); - final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault()); - final Geopoint coords = app.currentGeo().getCoords(); - final List<Address> addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1); - if (!addresses.isEmpty()) { - subscriber.onNext(formatAddress(addresses.get(0))); - } - subscriber.onCompleted(); - } catch (final Exception e) { - subscriber.onError(e); - } + public String call(final Address address) { + return formatAddress(address); } - }); - AndroidObservable.bindActivity(MainActivity.this, address.onErrorResumeNext(Observable.from(geo.getCoords().toString()))) + }).onErrorResumeNext(Observable.just(currentCoords.toString())); + AppObservable.bindActivity(MainActivity.this, address) .subscribeOn(RxUtils.networkScheduler) .subscribe(new Action1<String>() { @Override @@ -588,7 +596,7 @@ public class MainActivity extends AbstractActionBarActivity { }); } } else { - navLocation.setText(geo.getCoords().toString()); + navLocation.setText(currentCoords.toString()); } } } @@ -599,7 +607,7 @@ public class MainActivity extends AbstractActionBarActivity { */ public void cgeoFindOnMap(final View v) { findOnMap.setPressed(true); - CGeoMap.startActivityLiveMap(this); + startActivity(CGeoMap.getLiveMapIntent(this)); } /** @@ -607,12 +615,8 @@ public class MainActivity extends AbstractActionBarActivity { * unused here but needed since this method is referenced from XML layout */ public void cgeoFindNearest(final View v) { - if (app.currentGeo().getCoords() == null) { - return; - } - nearestView.setPressed(true); - CacheListActivity.startActivityNearest(this, app.currentGeo().getCoords()); + startActivity(CacheListActivity.getNearestIntent(this)); } /** @@ -659,86 +663,19 @@ public class MainActivity extends AbstractActionBarActivity { startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); } - private class CountBubbleUpdateThread extends Thread { - private final Handler countBubbleHandler = new Handler() { - - @Override - public void handleMessage(final Message msg) { - try { - if (countBubbleCnt == 0) { - countBubble.setVisibility(View.GONE); - } else { - countBubble.setText(Integer.toString(countBubbleCnt)); - countBubble.bringToFront(); - countBubble.setVisibility(View.VISIBLE); - } - } catch (final Exception e) { - Log.w("MainActivity.countBubbleHander", e); - } - } - }; - - @Override - public void run() { - if (app == null) { - return; - } - - int checks = 0; - while (!DataStore.isInitialized()) { - try { - sleep(500); - checks++; - } catch (final Exception e) { - Log.e("MainActivity.CountBubbleUpdateThread.run", e); - } - - if (checks > 10) { - return; - } - } - - countBubbleCnt = DataStore.getAllCachesCount(); - - countBubbleHandler.sendEmptyMessage(0); - } - } - - private class CleanDatabaseThread extends Thread { - - @Override - public void run() { - if (app == null) { - return; - } - if (cleanupRunning) { - return; - } - - boolean more = false; - if (version != Settings.getVersion()) { - Log.i("Initializing hard cleanup - version changed from " + Settings.getVersion() + " to " + version + "."); - - more = true; - } - - cleanupRunning = true; - DataStore.clean(more); - cleanupRunning = false; - - if (version > 0) { - Settings.setVersion(version); - } - } - } - private void checkShowChangelog() { - final long lastChecksum = Settings.getLastChangelogChecksum(); - final long checksum = TextUtils.checksum(getString(R.string.changelog_master) + getString(R.string.changelog_release)); - Settings.setLastChangelogChecksum(checksum); - // don't show change log after new install... - if (lastChecksum > 0 && lastChecksum != checksum) { - AboutActivity.showChangeLog(this); + // temporary workaround for #4143 + //TODO: understand and avoid if possible + try { + final long lastChecksum = Settings.getLastChangelogChecksum(); + final long checksum = TextUtils.checksum(getString(R.string.changelog_master) + getString(R.string.changelog_release)); + Settings.setLastChangelogChecksum(checksum); + // don't show change log after new install... + if (lastChecksum > 0 && lastChecksum != checksum) { + AboutActivity.showChangeLog(this); + } + } catch (final Exception ex) { + Log.e("Error checking/showing changelog!", ex); } } diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java index 2591987..b0d413d 100644 --- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java +++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java @@ -7,11 +7,12 @@ import butterknife.Optional; import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.activity.INavigationSource; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.geopoint.DistanceParser; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.location.DistanceParser; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.AbstractViewHolder; import cgeo.geocaching.ui.NavigationActionProvider; @@ -19,8 +20,13 @@ import cgeo.geocaching.ui.dialog.CoordinatesInputDialog; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.Nullable; + +import rx.functions.Action0; +import rx.schedulers.Schedulers; import android.app.Activity; import android.content.Context; @@ -94,7 +100,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen public View getView(final int position, final View convertView, final ViewGroup parent) { View rowView = convertView; - ViewHolder viewHolder; + final ViewHolder viewHolder; if (rowView == null) { rowView = getInflater().inflate(R.layout.simple_way_point, parent, false); viewHolder = new ViewHolder(rowView); @@ -261,7 +267,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen private void initializeDistanceUnitSelector() { if (StringUtils.isBlank(distanceUnit)) { - if (Settings.isUseImperialUnits()) { + if (Settings.useImperialUnits()) { distanceUnitSelector.setSelection(2); // ft distanceUnit = res.getStringArray(R.array.distance_units)[2]; } else { @@ -281,7 +287,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen if (latButton.getText().length() > 0 && lonButton.getText().length() > 0) { gp = new Geopoint(latButton.getText().toString() + " " + lonButton.getText().toString()); } - final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, gp, app.currentGeo()); + final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, gp, Sensors.getInstance().currentGeo()); coordsDialog.setCancelable(true); coordsDialog.show(getSupportFragmentManager(),"wpedit_dialog"); } @@ -336,7 +342,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen menu.findItem(R.id.menu_caches_around).setVisible(visible); menu.findItem(R.id.menu_clear_history).setVisible(!getHistoryOfSearchedLocations().isEmpty()); - } catch (final RuntimeException e) { + } catch (final RuntimeException ignored) { // nothing } @@ -346,20 +352,14 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen @Override public boolean onOptionsItemSelected(final MenuItem item) { final int menuItem = item.getItemId(); - - final Geopoint coords = getDestination(); - - if (coords != null) { - addToHistory(coords); - } - + final Geopoint coords = getDestinationAndAddToHistory(); switch (menuItem) { case R.id.menu_default_navigation: - navigateTo(); + navigateTo(coords); return true; case R.id.menu_caches_around: - cachesAround(); + cachesAround(coords); return true; case R.id.menu_clear_history: @@ -373,22 +373,33 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen return super.onOptionsItemSelected(item); } - private void addToHistory(final Geopoint coords) { + private Geopoint getDestinationAndAddToHistory() { + final Geopoint coords = getDestination(); + addToHistory(coords); + return coords; + } + + private void addToHistory(@Nullable final Geopoint coords) { + if (coords == null) { + return; + } + // Add locations to history final Destination loc = new Destination(coords); if (!getHistoryOfSearchedLocations().contains(loc)) { getHistoryOfSearchedLocations().add(0, loc); - - // Save location - DataStore.saveSearchedDestination(loc); - - // Ensure to remove the footer - historyListView.removeFooterView(getEmptyHistoryFooter()); - - runOnUiThread(new Runnable() { + RxUtils.andThenOnUi(Schedulers.io(), new Action0() { @Override - public void run() { + public void call() { + // Save location + DataStore.saveSearchedDestination(loc); + } + }, new Action0() { + @Override + public void call() { + // Ensure to remove the footer + historyListView.removeFooterView(getEmptyHistoryFooter()); destinationHistoryAdapter.notifyDataSetChanged(); } }); @@ -431,35 +442,34 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen } } - private void navigateTo() { - navigateTo(getDestination()); - } + private void navigateTo(final Geopoint coords) { + if (coords == null) { + showToast(res.getString(R.string.err_location_unknown)); + return; + } - private void navigateTo(final Geopoint geopoint) { - NavigationAppFactory.startDefaultNavigationApplication(1, this, geopoint); + NavigationAppFactory.startDefaultNavigationApplication(1, this, coords); } - private void cachesAround() { - final Geopoint coords = getDestination(); - + private void cachesAround(final Geopoint coords) { if (coords == null) { showToast(res.getString(R.string.err_location_unknown)); return; } - CacheListActivity.startActivityCoordinates(this, coords); + CacheListActivity.startActivityCoordinates(this, coords, null); finish(); } private final GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override - public void updateGeoData(final IGeoData geo) { + public void updateGeoData(final GeoData geo) { try { latButton.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); lonButton.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); } catch (final RuntimeException e) { - Log.w("Failed to update location."); + Log.w("Failed to update location", e); } } }; @@ -468,15 +478,9 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen @Override public void onClick(final View arg0) { - final Geopoint coords = app.currentGeo().getCoords(); - if (coords == null) { - showToast(res.getString(R.string.err_point_unknown_position)); - return; - } - + final Geopoint coords = Sensors.getInstance().currentGeo().getCoords(); latButton.setText(coords.format(GeopointFormatter.Format.LAT_DECMINUTE)); lonButton.setText(coords.format(GeopointFormatter.Format.LON_DECMINUTE)); - changed = false; } } @@ -504,30 +508,25 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen return null; } } else { - if (app.currentGeo().getCoords() == null) { - showToast(res.getString(R.string.err_point_curr_position_unavailable)); - return null; - } - - coords = app.currentGeo().getCoords(); + coords = Sensors.getInstance().currentGeo().getCoords(); } // apply projection - if (coords != null && StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) { + if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) { // bearing & distance - double bearing; + final double bearing; try { bearing = Double.parseDouble(bearingText); - } catch (final NumberFormatException e) { + } catch (final NumberFormatException ignored) { Dialogs.message(this, R.string.err_point_bear_and_dist_title, R.string.err_point_bear_and_dist); return null; } - double distance; + final double distance; try { distance = DistanceParser.parseDistance(distanceText, - !Settings.isUseImperialUnits()); - } catch (final NumberFormatException e) { + !Settings.useImperialUnits()); + } catch (final NumberFormatException ignored) { showToast(res.getString(R.string.err_parse_dist)); return null; } @@ -535,9 +534,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen coords = coords.project(bearing, distance); } - if (coords != null) { - saveCoords(coords); - } + saveCoords(coords); return coords; } @@ -551,11 +548,11 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen @Override public void startDefaultNavigation() { - navigateTo(); + navigateTo(getDestinationAndAddToHistory()); } @Override public void startDefaultNavigation2() { - NavigationAppFactory.startDefaultNavigationApplication(2, this, getDestination()); + NavigationAppFactory.startDefaultNavigationApplication(2, this, getDestinationAndAddToHistory()); } } diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java index 21f306e..27edffd 100644 --- a/main/src/cgeo/geocaching/PocketQueryList.java +++ b/main/src/cgeo/geocaching/PocketQueryList.java @@ -2,14 +2,10 @@ package cgeo.geocaching; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.gc.GCParser; -import cgeo.geocaching.utils.RxUtils; import org.apache.commons.collections4.CollectionUtils; -import rx.Observable; -import rx.Observable.OnSubscribe; -import rx.Subscriber; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import android.app.Activity; @@ -47,13 +43,7 @@ public final class PocketQueryList { public static void promptForListSelection(final Activity activity, final Action1<PocketQueryList> runAfterwards) { final Dialog waitDialog = ProgressDialog.show(activity, activity.getString(R.string.search_pocket_title), activity.getString(R.string.search_pocket_loading), true, true); - AndroidObservable.bindActivity(activity, Observable.create(new OnSubscribe<List<PocketQueryList>>() { - @Override - public void call(final Subscriber<? super List<PocketQueryList>> subscriber) { - subscriber.onNext(GCParser.searchPocketQueryList()); - subscriber.onCompleted(); - } - })).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<List<PocketQueryList>>() { + AppObservable.bindActivity(activity, GCParser.searchPocketQueryListObservable).subscribe(new Action1<List<PocketQueryList>>() { @Override public void call(final List<PocketQueryList> pocketQueryLists) { waitDialog.dismiss(); @@ -61,6 +51,7 @@ public final class PocketQueryList { } }); } + private static void selectFromPocketQueries(final Activity activity, final List<PocketQueryList> pocketQueryList, final Action1<PocketQueryList> runAfterwards) { if (CollectionUtils.isEmpty(pocketQueryList)) { ActivityMixin.showToast(activity, activity.getString(R.string.warn_no_pocket_query_found)); diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index edd611a..ea91857 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -9,10 +9,11 @@ import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.connector.capability.ISearchByGeocode; import cgeo.geocaching.connector.trackable.TrackableConnector; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; import cgeo.geocaching.search.AutoCompleteAdapter; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.GeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.dialog.CoordinatesInputDialog; import cgeo.geocaching.ui.dialog.Dialogs; @@ -62,6 +63,8 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin @InjectView(R.id.trackable) protected AutoCompleteTextView trackableEditText; @InjectView(R.id.display_trackable) protected Button buttonSearchTrackable; + private static final String GOOGLE_NOW_SEARCH_ACTION = "com.google.android.gms.actions.SEARCH_ACTION"; + @Override public final void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -81,8 +84,8 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin return; } - // search query - if (Intent.ACTION_SEARCH.equals(intent.getAction())) { + // search query, from search toolbar or from google now + if (Intent.ACTION_SEARCH.equals(intent.getAction()) || GOOGLE_NOW_SEARCH_ACTION.equals(intent.getAction())) { hideKeyboard(); final String query = intent.getStringExtra(SearchManager.QUERY); final boolean keywordSearch = intent.getBooleanExtra(Intents.EXTRA_KEYWORD_SEARCH, true); @@ -124,7 +127,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin /** * Performs a search for query either as geocode, trackable code or keyword * - * @param query + * @param nonTrimmedQuery * String to search for * @param keywordSearch * Set to true if keyword search should be performed if query isn't GC or TB @@ -142,7 +145,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin } final IConnector connector = ConnectorFactory.getConnector(geocode); - if (connector instanceof ISearchByGeocode) { + if (connector instanceof ISearchByGeocode && geocode != null) { CacheDetailActivity.startActivity(this, geocode.toUpperCase(Locale.US)); return true; } @@ -159,7 +162,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin } } - if (trackableConnector != ConnectorFactory.UNKNOWN_TRACKABLE_CONNECTOR) { + if (trackableConnector != ConnectorFactory.UNKNOWN_TRACKABLE_CONNECTOR && geocode != null) { final Intent trackablesIntent = new Intent(this, TrackableActivity.class); trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, geocode.toUpperCase(Locale.US)); startActivity(trackablesIntent); @@ -291,7 +294,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin } private void updateCoordinates() { - final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, null, app.currentGeo()); + final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, null, Sensors.getInstance().currentGeo()); coordsDialog.setCancelable(true); coordsDialog.show(getSupportFragmentManager(), "wpedit_dialog"); } @@ -307,14 +310,12 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin final String lonText = StringUtils.trim(buttonLongitude.getText().toString()); if (StringUtils.isEmpty(latText) || StringUtils.isEmpty(lonText)) { - final IGeoData geo = app.currentGeo(); - if (geo.getCoords() != null) { - buttonLatitude.setText(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE)); - buttonLongitude.setText(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE)); - } + final GeoData geo = Sensors.getInstance().currentGeo(); + buttonLatitude.setText(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE)); + buttonLongitude.setText(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE)); } else { try { - CacheListActivity.startActivityCoordinates(this, new Geopoint(latText, lonText)); + CacheListActivity.startActivityCoordinates(this, new Geopoint(latText, lonText), null); } catch (final Geopoint.ParseException e) { showToast(res.getString(e.resource)); } @@ -373,7 +374,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin } private void findByGeocodeFn() { - final String geocodeText = StringUtils.trim(geocodeEditText.getText().toString()); + final String geocodeText = StringUtils.trimToEmpty(geocodeEditText.getText().toString()); if (StringUtils.isBlank(geocodeText) || geocodeText.equalsIgnoreCase("GC")) { Dialogs.message(this, R.string.warn_search_help_title, R.string.warn_search_help_gccode); @@ -384,7 +385,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin } private void findTrackableFn() { - final String trackableText = StringUtils.trim(trackableEditText.getText().toString()); + final String trackableText = StringUtils.trimToEmpty(trackableEditText.getText().toString()); if (StringUtils.isBlank(trackableText) || trackableText.equalsIgnoreCase("TB")) { Dialogs.message(this, R.string.warn_search_help_title, R.string.warn_search_help_tb); diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index 74cc59d..5de1298 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import rx.Observable; +import rx.functions.Func0; import rx.functions.Func1; import rx.functions.Func2; @@ -215,10 +216,6 @@ public class SearchResult implements Parcelable { } /** - * @param excludeDisabled - * @param excludeMine - * @param cacheType - * @return */ public SearchResult filterSearchResults(final boolean excludeDisabled, final boolean excludeMine, final CacheType cacheType) { @@ -314,17 +311,17 @@ public class SearchResult implements Parcelable { public static <C extends IConnector> SearchResult parallelCombineActive(final Collection<C> connectors, final Func1<C, SearchResult> func) { - return Observable.from(connectors).parallel(new Func1<Observable<C>, Observable<SearchResult>>() { + return Observable.from(connectors).flatMap(new Func1<C, Observable<SearchResult>>() { @Override - public Observable<SearchResult> call(final Observable<C> cObservable) { - return cObservable.flatMap(new Func1<C, Observable<? extends SearchResult>>() { + public Observable<SearchResult> call(final C connector) { + return connector.isActive() ? Observable.defer(new Func0<Observable<SearchResult>>() { @Override - public Observable<? extends SearchResult> call(final C c) { - return c.isActive() ? Observable.from(func.call(c)) : Observable.<SearchResult>empty(); + public Observable<SearchResult> call() { + return Observable.just(func.call(connector)); } - }); + }).subscribeOn(RxUtils.networkScheduler) : Observable.<SearchResult>empty(); } - }, RxUtils.networkScheduler).reduce(new SearchResult(), new Func2<SearchResult, SearchResult, SearchResult>() { + }).reduce(new SearchResult(), new Func2<SearchResult, SearchResult, SearchResult>() { @Override public SearchResult call(final SearchResult searchResult, final SearchResult searchResult2) { searchResult.addSearchResult(searchResult2); diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java index dc898d7..a506f16 100644 --- a/main/src/cgeo/geocaching/SelectMapfileActivity.java +++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java @@ -33,7 +33,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio private String mapFile; - private static int REQUEST_DIRECTORY = 1; + private final static int REQUEST_DIRECTORY = 1; @Override public void onCreate(Bundle savedInstanceState) { @@ -53,7 +53,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, getString(android.R.string.ok)); startActivityForResult(dirChooser, REQUEST_DIRECTORY); - } catch (android.content.ActivityNotFoundException ex) { + } catch (android.content.ActivityNotFoundException ignored) { // OI file manager not available final Intent dirChooser = new Intent(SelectMapfileActivity.this, SimpleDirChooser.class); dirChooser.putExtra(Intents.EXTRA_START_DIR, LocalStorage.getStorage().getAbsolutePath()); @@ -87,7 +87,7 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio for (File dir : LocalStorage.getStorages()) { folders.add(new File(dir, "mfmaps")); folders.add(new File(new File(dir, "Locus"), "mapsVector")); - folders.add(new File(dir, LocalStorage.cache)); + folders.add(new File(dir, LocalStorage.CACHE_DIRNAME)); } return folders; } @@ -98,8 +98,8 @@ public class SelectMapfileActivity extends AbstractFileListActivity<FileSelectio } @Override - public void setCurrentFile(String newFile) { - mapFile = newFile; + public void setCurrentFile(String name) { + mapFile = name; } @Override diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java index ceceab9..be363f0 100644 --- a/main/src/cgeo/geocaching/StaticMapsActivity.java +++ b/main/src/cgeo/geocaching/StaticMapsActivity.java @@ -27,14 +27,11 @@ import java.util.List; @OptionsMenu(R.menu.static_maps_activity_options) public class StaticMapsActivity extends AbstractActionBarActivity { - private static final String EXTRAS_WAYPOINT = "waypoint"; - private static final String EXTRAS_DOWNLOAD = "download"; - private static final String EXTRAS_GEOCODE = "geocode"; - - @Extra(EXTRAS_DOWNLOAD) boolean download = false; - @Extra(EXTRAS_WAYPOINT) Integer waypointId = null; - @Extra(EXTRAS_GEOCODE) String geocode = null; + @Extra(Intents.EXTRA_DOWNLOAD) boolean download = false; + @Extra(Intents.EXTRA_WAYPOINT_ID) Integer waypointId = null; + @Extra(Intents.EXTRA_GEOCODE) String geocode = null; + private Geocache cache; private final List<Bitmap> maps = new ArrayList<>(); private LayoutInflater inflater = null; private ProgressDialog waitDialog = null; @@ -94,12 +91,16 @@ public class StaticMapsActivity extends AbstractActionBarActivity { public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.staticmaps_activity); - if (geocode == null) { - showToast("Sorry, c:geo forgot for what cache you want to load static maps."); + cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + + if (cache == null) { + Log.e("StaticMapsActivity.onCreate: cannot find the cache " + geocode); finish(); return; } + setCacheTitleBar(cache); + waitDialog = ProgressDialog.show(this, null, res.getString(R.string.map_static_loading), true); waitDialog.setCancelable(true); @@ -116,7 +117,6 @@ public class StaticMapsActivity extends AbstractActionBarActivity { for (int level = 1; level <= StaticMapsProvider.MAPS_LEVEL_MAX; level++) { try { if (waypointId != null) { - final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); final Bitmap image = StaticMapsProvider.getWaypointMap(geocode, cache.getWaypointById(waypointId), level); if (image != null) { maps.add(image); @@ -150,7 +150,6 @@ public class StaticMapsActivity extends AbstractActionBarActivity { } private boolean downloadStaticMaps() { - final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); if (waypointId == null) { showToast(res.getString(R.string.info_storing_static_maps)); RxUtils.waitForCompletion(StaticMapsProvider.storeCacheStaticMap(cache)); diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 030c379..8c399af 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -2,7 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.files.LocalStorage; -import cgeo.geocaching.geopoint.GeopointFormatter.Format; +import cgeo.geocaching.location.GeopointFormatter.Format; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; @@ -16,8 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import rx.Observable; -import rx.functions.Action0; -import rx.util.async.Async; +import rx.functions.Func0; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -38,6 +37,8 @@ public final class StaticMapsProvider { private static final String MAP_FILENAME_PREFIX = "map_"; private static final String MARKERS_URL = "http://status.cgeo.org/assets/markers/"; + private static volatile long last403 = 0; + /** We assume there is no real usable image with less than 1k. */ private static final int MIN_MAP_IMAGE_BYTES = 1000; @@ -54,32 +55,43 @@ public final class StaticMapsProvider { return LocalStorage.getStorageFile(geocode, MAP_FILENAME_PREFIX + prefix, false, createDirs); } + private static <T> Observable<T> checkDownloadPermission(final Observable<T> ifPermitted) { + return Observable.defer(new Func0<Observable<T>>() { + @Override + public Observable<T> call() { + if (System.currentTimeMillis() - last403 >= 30000) { + return ifPermitted; + } + Log.d("StaticMaps.downloadMap: request ignored because of recent \"permission denied\" answer"); + return Observable.empty(); + } + }); + } + private static Observable<String> downloadDifferentZooms(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int width, final int height, final Parameters waypoints) { - return Observable.merge(downloadMap(geocode, 20, SATELLITE, markerUrl, prefix + '1', "", latlonMap, width, height, waypoints), + return checkDownloadPermission(Observable.merge(downloadMap(geocode, 20, SATELLITE, markerUrl, prefix + '1', "", latlonMap, width, height, waypoints), downloadMap(geocode, 18, SATELLITE, markerUrl, prefix + '2', "", latlonMap, width, height, waypoints), downloadMap(geocode, 16, ROADMAP, markerUrl, prefix + '3', "", latlonMap, width, height, waypoints), downloadMap(geocode, 14, ROADMAP, markerUrl, prefix + '4', "", latlonMap, width, height, waypoints), - downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, width, height, waypoints)); + downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, width, height, waypoints))); } private static Observable<String> downloadMap(final String geocode, final int zoom, final String mapType, final String markerUrl, final String prefix, final String shadow, final String latlonMap, final int width, final int height, final Parameters waypoints) { - int scale = 1; - if (width > GOOGLE_MAPS_MAX_SIZE) { - scale = 2; - } + // If it has been less than 30 seconds since we got a 403 (permission denied) from Google servers, + // do not try again. + final int scale = width <= GOOGLE_MAPS_MAX_SIZE ? 1 : 2; final float aspectRatio = width / (float) height; final int requestWidth = Math.min(width / scale, GOOGLE_MAPS_MAX_SIZE); final int requestHeight = (aspectRatio > 1) ? Math.round(requestWidth / aspectRatio) : requestWidth; - final int requestScale = scale; final int requestZoom = Math.min((scale == 2) ? zoom + 1 : zoom, GOOGLE_MAX_ZOOM); - return Async.fromAction(new Action0() { + return checkDownloadPermission(Observable.defer(new Func0<Observable<String>>() { @Override - public void call() { + public Observable<String> call() { final Parameters params = new Parameters( "center", latlonMap, "zoom", String.valueOf(requestZoom), "size", String.valueOf(requestWidth) + 'x' + String.valueOf(requestHeight), - "scale", String.valueOf(requestScale), + "scale", String.valueOf(scale), "maptype", mapType, "markers", "icon:" + markerUrl + '|' + shadow + latlonMap, "sensor", "false"); @@ -90,11 +102,15 @@ public final class StaticMapsProvider { if (httpResponse == null) { Log.e("StaticMapsProvider.downloadMap: httpResponse is null"); - return; + return Observable.just(prefix); } - if (httpResponse.getStatusLine().getStatusCode() != 200) { - Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode()); - return; + final int statusCode = httpResponse.getStatusLine().getStatusCode(); + if (statusCode != 200) { + Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + statusCode); + if (statusCode == 403) { + last403 = System.currentTimeMillis(); + } + return Observable.just(prefix); } final File file = getMapFile(geocode, prefix, true); if (LocalStorage.saveEntityToFile(httpResponse, file)) { @@ -104,8 +120,9 @@ public final class StaticMapsProvider { FileUtils.deleteIgnoringFailure(file); } } + return Observable.just(prefix); } - }, prefix, RxUtils.networkScheduler); + }).subscribeOn(RxUtils.networkScheduler)); } public static Observable<String> downloadMaps(final Geocache cache) { @@ -132,16 +149,11 @@ public final class StaticMapsProvider { } - return Observable.merge(downloaders); + return checkDownloadPermission(Observable.merge(downloaders)); } /** * Deletes and download all Waypoints static maps. - * - * @param cache - * The cache instance - * @param edge - * The boundings */ private static Observable<String> refreshAllWpStaticMaps(final Geocache cache, final int width, final int height) { LocalStorage.deleteFilesWithPrefix(cache.getGeocode(), MAP_FILENAME_PREFIX + WAYPOINT_PREFIX); @@ -149,7 +161,7 @@ public final class StaticMapsProvider { for (final Waypoint waypoint : cache.getWaypoints()) { downloaders.add(storeWaypointStaticMap(cache.getGeocode(), width, height, waypoint)); } - return Observable.merge(downloaders); + return checkDownloadPermission(Observable.merge(downloaders)); } public static Observable<String> storeWaypointStaticMap(final Geocache cache, final Waypoint waypoint) { @@ -203,9 +215,8 @@ public final class StaticMapsProvider { public static Observable<String> storeCachePreviewMap(final Geocache cache) { final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); final Point displaySize = Compatibility.getDisplaySize(); - final int minSize = Math.min(displaySize.x, displaySize.y); final String markerUrl = MARKERS_URL + "my_location_mdpi.png"; - return downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, minSize, minSize, null); + return downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, displaySize.x, displaySize.y, null); } private static Observable<String> downloadMaps(final String geocode, final String markerUrl, final String prefix, @@ -248,7 +259,6 @@ public final class StaticMapsProvider { /** * Check if at least one map file exists for the given cache. * - * @param cache * @return <code>true</code> if at least one map file exists; <code>false</code> otherwise */ public static boolean hasStaticMap(@NonNull final Geocache cache) { @@ -268,8 +278,6 @@ public final class StaticMapsProvider { /** * Checks if at least one map file exists for the given geocode and waypoint ID. * - * @param geocode - * @param waypoint * @return <code>true</code> if at least one map file exists; <code>false</code> otherwise */ public static boolean hasStaticMapForWaypoint(final String geocode, final Waypoint waypoint) { @@ -287,8 +295,6 @@ public final class StaticMapsProvider { /** * Checks if all map files exist for the given geocode and waypoint ID. * - * @param geocode - * @param waypoint * @return <code>true</code> if all map files exist; <code>false</code> otherwise */ public static boolean hasAllStaticMapsForWaypoint(final String geocode, final Waypoint waypoint) { diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java index a228363..acc7011 100644 --- a/main/src/cgeo/geocaching/StatusFragment.java +++ b/main/src/cgeo/geocaching/StatusFragment.java @@ -1,15 +1,15 @@ package cgeo.geocaching; import butterknife.ButterKnife; +import butterknife.InjectView; import cgeo.geocaching.network.StatusUpdater; import cgeo.geocaching.network.StatusUpdater.Status; import cgeo.geocaching.utils.Log; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; -import rx.schedulers.Schedulers; import rx.subscriptions.Subscriptions; import android.content.Intent; @@ -26,15 +26,17 @@ import android.widget.TextView; public class StatusFragment extends Fragment { + protected @InjectView(R.id.status_icon) ImageView statusIcon; + protected @InjectView(R.id.status_message) TextView statusMessage; + private Subscription statusSubscription = Subscriptions.empty(); @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); final ViewGroup statusGroup = (ViewGroup) inflater.inflate(R.layout.status, container, false); - final ImageView statusIcon = ButterKnife.findById(statusGroup, R.id.status_icon); - final TextView statusMessage = ButterKnife.findById(statusGroup, R.id.status_message); - statusSubscription = AndroidObservable.bindFragment(this, StatusUpdater.latestStatus).subscribeOn(Schedulers.io()) + ButterKnife.inject(this, statusGroup); + statusSubscription = AppObservable.bindFragment(this, StatusUpdater.latestStatus) .subscribe(new Action1<Status>() { @Override public void call(final Status status) { @@ -89,6 +91,7 @@ public class StatusFragment extends Fragment { public void onDestroyView() { statusSubscription.unsubscribe(); super.onDestroyView(); + ButterKnife.reset(this); } } diff --git a/main/src/cgeo/geocaching/Trackable.java b/main/src/cgeo/geocaching/Trackable.java index 9c2b044..6ec8c0d 100644 --- a/main/src/cgeo/geocaching/Trackable.java +++ b/main/src/cgeo/geocaching/Trackable.java @@ -3,17 +3,21 @@ package cgeo.geocaching; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.utils.ImageUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.text.Html; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.LinkedList; import java.util.List; public class Trackable implements ILogable { - static final public int SPOTTED_UNSET = 0; + static final private int SPOTTED_UNSET = 0; static final public int SPOTTED_CACHE = 1; static final public int SPOTTED_USER = 2; static final public int SPOTTED_UNKNOWN = 3; @@ -38,10 +42,19 @@ public class Trackable implements ILogable { private List<LogEntry> logs = new ArrayList<>(); private String trackingcode = null; + /** + * Check whether this trackable has a corresponding URL. + */ + public boolean hasUrl() { + return getConnector().hasTrackableUrls(); + } + + @NonNull public String getUrl() { return getConnector().getUrl(this); } + @NonNull private TrackableConnector getConnector() { return ConnectorFactory.getConnector(this); } @@ -50,7 +63,7 @@ public class Trackable implements ILogable { return guid; } - public void setGuid(String guid) { + public void setGuid(final String guid) { this.guid = guid; } @@ -59,7 +72,7 @@ public class Trackable implements ILogable { return geocode; } - public void setGeocode(String geocode) { + public void setGeocode(final String geocode) { this.geocode = StringUtils.upperCase(geocode); } @@ -67,7 +80,7 @@ public class Trackable implements ILogable { return iconUrl; } - public void setIconUrl(String iconUrl) { + public void setIconUrl(final String iconUrl) { this.iconUrl = iconUrl; } @@ -76,7 +89,7 @@ public class Trackable implements ILogable { return name; } - public void setName(String name) { + public void setName(final String name) { this.name = name; } @@ -84,7 +97,7 @@ public class Trackable implements ILogable { return type; } - public void setType(String type) { + public void setType(final String type) { this.type = type; } @@ -92,7 +105,7 @@ public class Trackable implements ILogable { return released; } - public void setReleased(Date released) { + public void setReleased(final Date released) { if (released == null) { this.released = null; } @@ -105,7 +118,7 @@ public class Trackable implements ILogable { return distance; } - public void setDistance(float distance) { + public void setDistance(final float distance) { this.distance = distance; } @@ -113,7 +126,7 @@ public class Trackable implements ILogable { return origin; } - public void setOrigin(String origin) { + public void setOrigin(final String origin) { this.origin = origin; } @@ -121,7 +134,7 @@ public class Trackable implements ILogable { return owner; } - public void setOwner(String owner) { + public void setOwner(final String owner) { this.owner = owner; } @@ -129,7 +142,7 @@ public class Trackable implements ILogable { return ownerGuid; } - public void setOwnerGuid(String ownerGuid) { + public void setOwnerGuid(final String ownerGuid) { this.ownerGuid = ownerGuid; } @@ -137,7 +150,7 @@ public class Trackable implements ILogable { return spottedName; } - public void setSpottedName(String spottedName) { + public void setSpottedName(final String spottedName) { this.spottedName = spottedName; } @@ -145,7 +158,7 @@ public class Trackable implements ILogable { return spottedType; } - public void setSpottedType(int spottedType) { + public void setSpottedType(final int spottedType) { this.spottedType = spottedType; } @@ -153,7 +166,7 @@ public class Trackable implements ILogable { return spottedGuid; } - public void setSpottedGuid(String spottedGuid) { + public void setSpottedGuid(final String spottedGuid) { this.spottedGuid = spottedGuid; } @@ -161,7 +174,7 @@ public class Trackable implements ILogable { return goal; } - public void setGoal(String goal) { + public void setGoal(final String goal) { this.goal = goal; } @@ -169,7 +182,7 @@ public class Trackable implements ILogable { return details; } - public void setDetails(String details) { + public void setDetails(final String details) { this.details = details; } @@ -177,15 +190,16 @@ public class Trackable implements ILogable { return image; } - public void setImage(String image) { + public void setImage(final String image) { this.image = image; } + @NonNull public List<LogEntry> getLogs() { return logs; } - public void setLogs(List<LogEntry> logs) { + public void setLogs(final List<LogEntry> logs) { this.logs = logs != null ? logs : new ArrayList<LogEntry>(); } @@ -210,11 +224,25 @@ public class Trackable implements ILogable { return trackingcode; } - public void setTrackingcode(String trackingcode) { + public void setTrackingcode(final String trackingcode) { this.trackingcode = trackingcode; } - static public List<LogType> getPossibleLogTypes() { + @NonNull + public Collection<Image> getImages() { + final List<Image> images = new LinkedList<>(); + if (StringUtils.isNotBlank(image)) { + images.add(new Image(image, StringUtils.defaultIfBlank(name, geocode))); + } + ImageUtils.addImagesFromHtml(images, geocode, getDetails()); + for (final LogEntry log : getLogs()) { + images.addAll(log.getLogImages()); + } + return images; + } + + @NonNull + static List<LogType> getPossibleLogTypes() { final List<LogType> logTypes = new ArrayList<>(); logTypes.add(LogType.RETRIEVED_IT); logTypes.add(LogType.GRABBED_IT); diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index 0e784bd..7d10d34 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -4,40 +4,46 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.activity.AbstractActivity.ActivitySharingInterface; import cgeo.geocaching.activity.AbstractViewPagerActivity; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.connector.trackable.TravelBugConnector; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.network.AndroidBeam; import cgeo.geocaching.network.HtmlImage; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; import cgeo.geocaching.ui.CacheDetailsCreator; +import cgeo.geocaching.ui.ImagesList; import cgeo.geocaching.ui.UserActionsClickListener; import cgeo.geocaching.ui.UserNameClickListener; import cgeo.geocaching.ui.logs.TrackableLogsViewCreator; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.UnknownTagsHandler; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.eclipse.jdt.annotation.Nullable; -import rx.android.observables.AndroidObservable; -import rx.android.observables.ViewObservable; +import rx.Observable; +import rx.android.app.AppObservable; +import rx.android.view.OnClickEvent; +import rx.android.view.ViewObservable; import rx.functions.Action1; +import rx.functions.Func0; +import rx.subscriptions.CompositeSubscription; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.support.v7.app.ActionBar; import android.support.v7.view.ActionMode; import android.text.Html; @@ -57,11 +63,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivity.Page> implements ActivitySharingInterface { +public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivity.Page> implements AndroidBeam.ActivitySharingInterface { + + private CompositeSubscription createSubscriptions; public enum Page { DETAILS(R.string.detail), - LOGS(R.string.cache_logs); + LOGS(R.string.cache_logs), + IMAGES(R.string.cache_images); private final int resId; @@ -77,50 +86,9 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi private String id = null; private LayoutInflater inflater = null; private ProgressDialog waitDialog = null; - private final Handler loadTrackableHandler = new Handler() { - - @Override - public void handleMessage(final Message msg) { - if (trackable == null) { - if (waitDialog != null) { - waitDialog.dismiss(); - } - - if (StringUtils.isNotBlank(geocode)) { - showToast(res.getString(R.string.err_tb_find) + " " + geocode + "."); - } else { - showToast(res.getString(R.string.err_tb_find_that)); - } - - finish(); - return; - } - - try { - inflater = getLayoutInflater(); - geocode = trackable.getGeocode(); - - if (StringUtils.isNotBlank(trackable.getName())) { - setTitle(Html.fromHtml(trackable.getName()).toString()); - } else { - setTitle(trackable.getName()); - } - - invalidateOptionsMenuCompatible(); - reinitializeViewPager(); - - } catch (final Exception e) { - Log.e("TrackableActivity.loadTrackableHandler: ", e); - } - - if (waitDialog != null) { - waitDialog.dismiss(); - } - - } - }; - private CharSequence clickedItemText = null; + private ImagesList imagesList = null; + /** * Action mode of the current contextual action bar (e.g. for copy and share actions). */ @@ -129,16 +97,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.viewpager_activity); + createSubscriptions = new CompositeSubscription(); // set title in code, as the activity needs a hard coded title due to the intent filters setTitle(res.getString(R.string.trackable)); // get parameters final Bundle extras = getIntent().getExtras(); - final Uri uri = getIntent().getData(); - // try to get data from extras + final Uri uri = AndroidBeam.getUri(getIntent()); if (extras != null) { + // try to get data from extras geocode = extras.getString(Intents.EXTRA_GEOCODE); name = extras.getString(Intents.EXTRA_NAME); guid = extras.getString(Intents.EXTRA_GUID); @@ -150,7 +119,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi geocode = ConnectorFactory.getTrackableFromURL(uri.toString()); final String uriHost = uri.getHost().toLowerCase(Locale.US); - if (uriHost.contains("geocaching.com")) { + if (uriHost.endsWith("geocaching.com")) { geocode = uri.getQueryParameter("tracker"); guid = uri.getQueryParameter("guid"); id = uri.getQueryParameter("id"); @@ -172,17 +141,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi finish(); return; } - } else if (uriHost.contains("coord.info")) { - final String uriPath = uri.getPath().toLowerCase(Locale.US); - if (StringUtils.startsWith(uriPath, "/tb")) { - geocode = uriPath.substring(1).toUpperCase(Locale.US); - guid = null; - id = null; - } else { - showToast(res.getString(R.string.err_tb_details_open)); - finish(); - return; - } } } @@ -193,7 +151,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi return; } - String message; + final String message; if (StringUtils.isNotBlank(name)) { message = Html.fromHtml(name).toString(); } else if (StringUtils.isNotBlank(geocode)) { @@ -201,17 +159,34 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } else { message = res.getString(R.string.trackable); } - waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true); - // If we have a newer Android device setup Android Beam for easy cache sharing - initializeAndroidBeam(this); + AndroidBeam.enable(this, this); - createViewPager(0, null); - final LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id); - thread.start(); + createViewPager(0, new OnPageSelectedListener() { + @Override + public void onPageSelected(final int position) { + // Lazy loading of trackable images + if (getPage(position) == Page.IMAGES) { + loadTrackableImages(); + } + } + }); + refreshTrackable(message); } + private void refreshTrackable(final String message) { + waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true); + createSubscriptions.add(AppObservable.bindActivity(this, loadTrackable(geocode, guid, id)).singleOrDefault(null).subscribe(new Action1<Trackable>() { + @Override + public void call(final Trackable trackable) { + TrackableActivity.this.trackable = trackable; + displayTrackable(); + } + })); + } + + @Nullable @Override public String getAndroidBeamUri() { return trackable != null ? trackable.getUrl() : null; @@ -227,7 +202,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case R.id.menu_log_touch: - LogTrackableActivity.startActivity(this, trackable); + startActivityForResult(LogTrackableActivity.getIntent(this, trackable), LogTrackableActivity.LOG_TRACKABLE); return true; case R.id.menu_browser_trackable: startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl()))); @@ -240,92 +215,90 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi public boolean onPrepareOptionsMenu(final Menu menu) { if (trackable != null) { menu.findItem(R.id.menu_log_touch).setVisible(StringUtils.isNotBlank(geocode) && trackable.isLoggable()); - menu.findItem(R.id.menu_browser_trackable).setVisible(StringUtils.isNotBlank(trackable.getUrl())); + menu.findItem(R.id.menu_browser_trackable).setVisible(trackable.hasUrl()); } return super.onPrepareOptionsMenu(menu); } - private class LoadTrackableThread extends Thread { - final private Handler handler; - final private String geocode; - final private String guid; - final private String id; - - public LoadTrackableThread(final Handler handlerIn, final String geocodeIn, final String guidIn, final String idIn) { - handler = handlerIn; - geocode = geocodeIn; - guid = guidIn; - id = idIn; - } - - @Override - public void run() { - if (StringUtils.isNotEmpty(geocode)) { - - // iterate over the connectors as some codes may be handled by multiple connectors - for (final TrackableConnector trackableConnector : ConnectorFactory.getTrackableConnectors()) { - if (trackableConnector.canHandleTrackable(geocode)) { - trackable = trackableConnector.searchTrackable(geocode, guid, id); - if (trackable != null) { - break; + private static Observable<Trackable> loadTrackable(final String geocode, final String guid, final String id) { + return Observable.defer(new Func0<Observable<Trackable>>() { + @Override + public Observable<Trackable> call() { + if (StringUtils.isNotEmpty(geocode)) { + // iterate over the connectors as some codes may be handled by multiple connectors + for (final TrackableConnector trackableConnector : ConnectorFactory.getTrackableConnectors()) { + if (trackableConnector.canHandleTrackable(geocode)) { + final Trackable trackable = trackableConnector.searchTrackable(geocode, guid, id); + if (trackable != null) { + return Observable.just(trackable); + } } } + // Check local storage (offline case) + final Trackable trackable = DataStore.loadTrackable(geocode); + if (trackable != null) { + return Observable.just(trackable); + } } - // Check local storage (offline case) - if (trackable == null) { - trackable = DataStore.loadTrackable(geocode); - } - } - // fall back to GC search by GUID - if (trackable == null) { - trackable = TravelBugConnector.getInstance().searchTrackable(geocode, guid, id); + + // Fall back to GC search by GUID + final Trackable trackable = TravelBugConnector.getInstance().searchTrackable(geocode, guid, id); + return trackable != null ? Observable.just(trackable) : Observable.<Trackable>empty(); } - handler.sendMessage(Message.obtain()); - } + }).subscribeOn(RxUtils.networkScheduler); } - private class TrackableIconThread extends Thread { - final private String url; - final private Handler handler; + public void displayTrackable() { + if (trackable == null) { + if (waitDialog != null) { + waitDialog.dismiss(); + } - public TrackableIconThread(final String urlIn, final Handler handlerIn) { - url = urlIn; - handler = handlerIn; + if (StringUtils.isNotBlank(geocode)) { + showToast(res.getString(R.string.err_tb_find) + " " + geocode + "."); + } else { + showToast(res.getString(R.string.err_tb_find_that)); + } + + finish(); + return; } - @Override - public void run() { - if (url == null || handler == null) { - return; + try { + inflater = getLayoutInflater(); + geocode = trackable.getGeocode(); + + if (StringUtils.isNotBlank(trackable.getName())) { + setTitle(Html.fromHtml(trackable.getName()).toString()); + } else { + setTitle(trackable.getName()); } - try { - final HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false); + invalidateOptionsMenuCompatible(); + reinitializeViewPager(); - final BitmapDrawable image = imgGetter.getDrawable(url); - final Message message = handler.obtainMessage(0, image); - handler.sendMessage(message); - } catch (final Exception e) { - Log.e("TrackableActivity.TrackableIconThread.run: ", e); - } + } catch (final Exception e) { + Log.e("TrackableActivity.loadTrackableHandler: ", e); } - } - - private static class TrackableIconHandler extends Handler { - final private ActionBar view; - public TrackableIconHandler(final ActionBar viewIn) { - view = viewIn; + if (waitDialog != null) { + waitDialog.dismiss(); } - @Override - public void handleMessage(final Message message) { - final BitmapDrawable image = (BitmapDrawable) message.obj; - if (image != null && view != null) { - image.setBounds(0, 0, view.getHeight(), view.getHeight()); - view.setIcon(image); + } + + private void setupIcon(final ActionBar actionBar, final String url) { + final HtmlImage imgGetter = new HtmlImage(HtmlImage.SHARED, false, 0, false); + AppObservable.bindActivity(this, imgGetter.fetchDrawable(url)).subscribe(new Action1<BitmapDrawable>() { + @Override + public void call(final BitmapDrawable image) { + if (actionBar != null) { + final int height = actionBar.getHeight(); + image.setBounds(0, 0, height, height); + actionBar.setIcon(image); + } } - } + }); } public static void startActivity(final AbstractActivity fromContext, @@ -343,11 +316,38 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi case DETAILS: return new DetailsViewCreator(); case LOGS: - return new TrackableLogsViewCreator(this, trackable); + return new TrackableLogsViewCreator(this); + case IMAGES: + return new ImagesViewCreator(); } throw new IllegalStateException(); // cannot happen as long as switch case is enum complete } + private class ImagesViewCreator extends AbstractCachingPageViewCreator<View> { + + @Override + public View getDispatchedView(final ViewGroup parentView) { + view = getLayoutInflater().inflate(R.layout.cachedetail_images_page, parentView, false); + return view; + } + } + + private void loadTrackableImages() { + if (imagesList != null) { + return; + } + final PageViewCreator creator = getViewCreator(Page.IMAGES); + if (creator == null) { + return; + } + final View imageView = creator.getView(null); + if (imageView == null) { + return; + } + imagesList = new ImagesList(this, trackable.getGeocode()); + createSubscriptions.add(imagesList.loadImages(imageView, trackable.getImages(), false)); + } + @Override protected String getTitle(final Page page) { return res.getString(page.resId); @@ -357,9 +357,12 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi protected Pair<List<? extends Page>, Integer> getOrderedPages() { final List<Page> pages = new ArrayList<>(); pages.add(Page.DETAILS); - if (!trackable.getLogs().isEmpty()) { + if (CollectionUtils.isNotEmpty(trackable.getLogs())) { pages.add(Page.LOGS); } + if (CollectionUtils.isNotEmpty(trackable.getImages())) { + pages.add(Page.IMAGES); + } return new ImmutablePair<List<? extends Page>, Integer>(pages, 0); } @@ -382,16 +385,14 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi // action bar icon if (StringUtils.isNotBlank(trackable.getIconUrl())) { - final TrackableIconHandler iconHandler = new TrackableIconHandler(getSupportActionBar()); - final TrackableIconThread iconThread = new TrackableIconThread(trackable.getIconUrl(), iconHandler); - iconThread.start(); + setupIcon(getSupportActionBar(), trackable.getIconUrl()); } // trackable name - addContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown))); + addContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown)).right); // trackable type - String tbType; + final String tbType; if (StringUtils.isNotBlank(trackable.getType())) { tbType = Html.fromHtml(trackable.getType()).toString(); } else { @@ -400,10 +401,10 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi details.add(R.string.trackable_type, tbType); // trackable geocode - addContextMenu(details.add(R.string.trackable_code, trackable.getGeocode())); + addContextMenu(details.add(R.string.trackable_code, trackable.getGeocode()).right); // trackable owner - final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)); + final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)).right; if (StringUtils.isNotBlank(trackable.getOwner())) { owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE); owner.setOnClickListener(new UserActionsClickListener(trackable)); @@ -413,34 +414,39 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi if (StringUtils.isNotBlank(trackable.getSpottedName()) || trackable.getSpottedType() == Trackable.SPOTTED_UNKNOWN || trackable.getSpottedType() == Trackable.SPOTTED_OWNER) { + + final StringBuilder text; boolean showTimeSpan = true; - StringBuilder text; - - if (trackable.getSpottedType() == Trackable.SPOTTED_CACHE) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_in_cache) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); - } else if (trackable.getSpottedType() == Trackable.SPOTTED_USER) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_at_user) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); - } else if (trackable.getSpottedType() == Trackable.SPOTTED_UNKNOWN) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_unknown_location)); - } else if (trackable.getSpottedType() == Trackable.SPOTTED_OWNER) { - text = new StringBuilder(res.getString(R.string.trackable_spotted_owner)); - } else { - text = new StringBuilder("N/A"); - showTimeSpan = false; + switch (trackable.getSpottedType()) { + case Trackable.SPOTTED_CACHE: + text = new StringBuilder(res.getString(R.string.trackable_spotted_in_cache) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); + break; + case Trackable.SPOTTED_USER: + text = new StringBuilder(res.getString(R.string.trackable_spotted_at_user) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString()); + break; + case Trackable.SPOTTED_UNKNOWN: + text = new StringBuilder(res.getString(R.string.trackable_spotted_unknown_location)); + break; + case Trackable.SPOTTED_OWNER: + text = new StringBuilder(res.getString(R.string.trackable_spotted_owner)); + break; + default: + text = new StringBuilder("N/A"); + showTimeSpan = false; + break; } // days since last spotting - if (showTimeSpan && trackable.getLogs() != null) { + if (showTimeSpan) { for (final LogEntry log : trackable.getLogs()) { if (log.type == LogType.RETRIEVED_IT || log.type == LogType.GRABBED_IT || log.type == LogType.DISCOVERED_IT || log.type == LogType.PLACED_IT) { - final int days = log.daysSinceLog(); - text.append(" (").append(res.getQuantityString(R.plurals.days_ago, days, days)).append(')'); + text.append(" (").append(Formatter.formatDaysAgo(log.date)).append(')'); break; } } } - final TextView spotted = details.add(R.string.trackable_spotted, text.toString()); + final TextView spotted = details.add(R.string.trackable_spotted, text.toString()).right; spotted.setClickable(true); if (Trackable.SPOTTED_CACHE == trackable.getSpottedType()) { spotted.setOnClickListener(new View.OnClickListener() { @@ -467,19 +473,19 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi // trackable origin if (StringUtils.isNotBlank(trackable.getOrigin())) { - final TextView origin = details.add(R.string.trackable_origin, ""); + final TextView origin = details.add(R.string.trackable_origin, "").right; origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE); addContextMenu(origin); } // trackable released if (trackable.getReleased() != null) { - addContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()))); + addContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime())).right); } // trackable distance if (trackable.getDistance() >= 0) { - addContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()))); + addContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance())).right); } // trackable goal @@ -507,14 +513,14 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi trackableImage.setImageResource(R.drawable.image_not_loaded); trackableImage.setClickable(true); - ViewObservable.clicks(trackableImage, false).subscribe(new Action1<View>() { + ViewObservable.clicks(trackableImage, false).subscribe(new Action1<OnClickEvent>() { @Override - public void call(final View view) { + public void call(final OnClickEvent onClickEvent) { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getImage()))); } }); - AndroidObservable.bindActivity(TrackableActivity.this, new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage())).subscribe(new Action1<BitmapDrawable>() { + AppObservable.bindActivity(TrackableActivity.this, new HtmlImage(geocode, true, 0, false).fetchDrawable(trackable.getImage())).subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable bitmapDrawable) { trackableImage.setImageDrawable(bitmapDrawable); @@ -555,6 +561,10 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi @Override public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) { + return prepareClipboardActionMode(view, actionMode, menu); + } + + private boolean prepareClipboardActionMode(final View view, final ActionMode actionMode, final Menu menu) { final int viewId = view.getId(); assert view instanceof TextView; clickedItemText = ((TextView) view).getText(); @@ -584,6 +594,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi @Override public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) { actionMode.getMenuInflater().inflate(R.menu.details_context, menu); + prepareClipboardActionMode(view, actionMode, menu); return true; } @@ -595,4 +606,21 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi return false; } + @Override + protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { + // Refresh the logs view after coming back from logging a trackable + if (requestCode == LogTrackableActivity.LOG_TRACKABLE && resultCode == RESULT_OK) { + refreshTrackable(StringUtils.defaultIfBlank(trackable.getName(), trackable.getGeocode())); + } + } + + @Override + protected void onDestroy() { + createSubscriptions.unsubscribe(); + super.onDestroy(); + } + + public Trackable getTrackable() { + return trackable; + } } diff --git a/main/src/cgeo/geocaching/UsefulAppsActivity.java b/main/src/cgeo/geocaching/UsefulAppsActivity.java index a2cdaf7..d4517dc 100644 --- a/main/src/cgeo/geocaching/UsefulAppsActivity.java +++ b/main/src/cgeo/geocaching/UsefulAppsActivity.java @@ -5,8 +5,10 @@ import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActionBarActivity; import cgeo.geocaching.ui.AbstractViewHolder; +import cgeo.geocaching.utils.ProcessUtils; + +import org.eclipse.jdt.annotation.NonNull; -import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -36,27 +38,16 @@ public class UsefulAppsActivity extends AbstractActionBarActivity { private final int titleId; private final int descriptionId; private final int iconId; + @NonNull private final String packageName; - public HelperApp(final int title, final int description, final int icon, final String packageName) { + public HelperApp(final int title, final int description, final int icon, @NonNull final String packageName) { this.titleId = title; this.descriptionId = description; this.iconId = icon; this.packageName = packageName; } - private void installFromMarket(final Activity activity) { - try { - // allow also opening pure http URLs in addition to market packages - final String url = (packageName.startsWith("http:")) ? packageName : "market://details?id=" + packageName; - final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - activity.startActivity(marketIntent); - - } catch (final RuntimeException e) { - // market not available in standard emulator - } - } } private static final HelperApp[] HELPER_APPS = { @@ -106,7 +97,12 @@ public class UsefulAppsActivity extends AbstractActionBarActivity { @Override public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { final HelperApp helperApp = HELPER_APPS[position]; - helperApp.installFromMarket(UsefulAppsActivity.this); + if (helperApp.packageName.startsWith("http")) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(helperApp.packageName))); + } + else { + ProcessUtils.openMarket(UsefulAppsActivity.this, helperApp.packageName); + } } }); } diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java index 7381aab..cc00b1c 100644 --- a/main/src/cgeo/geocaching/Waypoint.java +++ b/main/src/cgeo/geocaching/Waypoint.java @@ -2,7 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; @@ -21,13 +21,13 @@ public class Waypoint implements IWaypoint { public static final String PREFIX_OWN = "OWN"; private static final int ORDER_UNDEFINED = -2; + private static final Pattern PATTERN_COORDS = Pattern.compile("\\b[nNsS]\\s*\\d"); private int id = -1; private String geocode = "geocode"; private WaypointType waypointType = WaypointType.WAYPOINT; private String prefix = ""; private String lookup = ""; private String name = ""; - private String latlon = ""; private Geopoint coords = null; private String note = ""; private int cachedOrder = ORDER_UNDEFINED; @@ -37,8 +37,6 @@ public class Waypoint implements IWaypoint { /** * require name and type for every waypoint * - * @param name - * @param type */ public Waypoint(final String name, final WaypointType type, final boolean own) { this.name = name; @@ -49,7 +47,6 @@ public class Waypoint implements IWaypoint { /** * copy constructor * - * @param other */ public Waypoint(final Waypoint other) { merge(other); @@ -67,9 +64,6 @@ public class Waypoint implements IWaypoint { if (StringUtils.isBlank(name)) { setName(old.name); } - if (StringUtils.isBlank(latlon) || latlon.startsWith("?")) { // there are waypoints containing "???" - latlon = old.latlon; - } if (coords == null) { coords = old.coords; } @@ -100,18 +94,11 @@ public class Waypoint implements IWaypoint { if (newPrefixes.containsKey(prefix)) { newPrefixes.get(prefix).merge(oldWaypoint); } else if (oldWaypoint.isUserDefined() || forceMerge) { - // personal note waypoints should always be taken from the new list only - if (!isPersonalNoteWaypoint(oldWaypoint)) { - newPoints.add(oldWaypoint); - } + newPoints.add(oldWaypoint); } } } - private static boolean isPersonalNoteWaypoint(final @NonNull Waypoint waypoint) { - return StringUtils.startsWith(waypoint.getName(), CgeoApplication.getInstance().getString(R.string.cache_personal_note) + " "); - } - public boolean isUserDefined() { return own || WaypointType.OWN == waypointType; } @@ -160,6 +147,7 @@ public class Waypoint implements IWaypoint { cachedOrder = ORDER_UNDEFINED; } + @NonNull public String getUrl() { return "http://www.geocaching.com/seek/cache_details.aspx?wp=" + geocode; } @@ -204,14 +192,6 @@ public class Waypoint implements IWaypoint { this.name = name; } - public String getLatlon() { - return latlon; - } - - public void setLatlon(final String latlon) { - this.latlon = latlon; - } - @Override public Geopoint getCoords() { return coords; @@ -279,7 +259,6 @@ public class Waypoint implements IWaypoint { /** * Delegates the creation of the waypoint-id for gpx-export to the waypoint * - * @return */ public String getGpxId() { @@ -303,10 +282,9 @@ public class Waypoint implements IWaypoint { */ public static Collection<Waypoint> parseWaypointsFromNote(@NonNull final String initialNote) { final List<Waypoint> waypoints = new LinkedList<>(); - final Pattern COORDPATTERN = Pattern.compile("\\b[nNsS]{1}\\s*\\d"); // begin of coordinates String note = initialNote; - MatcherWrapper matcher = new MatcherWrapper(COORDPATTERN, note); + MatcherWrapper matcher = new MatcherWrapper(PATTERN_COORDS, note); int count = 1; while (matcher.find()) { try { @@ -316,17 +294,16 @@ public class Waypoint implements IWaypoint { ((point.getLatitudeE6() % 1000) != 0 || (point.getLongitudeE6() % 1000) != 0)) { final String name = CgeoApplication.getInstance().getString(R.string.cache_personal_note) + " " + count; final String potentialWaypointType = note.substring(Math.max(0, matcher.start() - 15)); - final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), false); + final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), true); waypoint.setCoords(point); waypoints.add(waypoint); count++; } - } catch (final Geopoint.ParseException e) { - // ignore + } catch (final Geopoint.ParseException ignored) { } note = note.substring(matcher.start() + 1); - matcher = new MatcherWrapper(COORDPATTERN, note); + matcher = new MatcherWrapper(PATTERN_COORDS, note); } return waypoints; } diff --git a/main/src/cgeo/geocaching/WaypointPopupFragment.java b/main/src/cgeo/geocaching/WaypointPopupFragment.java index 03d95e5..227e30d 100644 --- a/main/src/cgeo/geocaching/WaypointPopupFragment.java +++ b/main/src/cgeo/geocaching/WaypointPopupFragment.java @@ -4,9 +4,9 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.utils.Log; @@ -48,8 +48,8 @@ public class WaypointPopupFragment extends AbstractDialogFragment { } @Override - protected void onUpdateGeoData(IGeoData geo) { - if (geo.getCoords() != null && waypoint != null && waypoint.getCoords() != null) { + protected void onUpdateGeoData(GeoData geo) { + if (waypoint != null && waypoint.getCoords() != null) { waypointDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(waypoint.getCoords()))); waypointDistance.bringToFront(); } @@ -60,6 +60,13 @@ public class WaypointPopupFragment extends AbstractDialogFragment { super.init(); waypoint = DataStore.loadWaypoint(waypointId); + + if (waypoint == null) { + Log.e("WaypointPopupFragment.init: unable to get waypoint " + waypointId); + getActivity().finish(); + return; + } + try { if (StringUtils.isNotBlank(waypoint.getName())) { setTitle(waypoint.getName()); diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index cc9931a..6ceead0 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -3,7 +3,10 @@ package cgeo.geocaching.activity; import butterknife.ButterKnife; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.network.AndroidBeam; import cgeo.geocaching.network.Cookies; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.ClipboardUtils; @@ -13,18 +16,13 @@ import cgeo.geocaching.utils.TranslationUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.Subscription; import rx.subscriptions.Subscriptions; -import android.annotation.TargetApi; import android.content.Intent; import android.content.res.Resources; -import android.nfc.NdefMessage; -import android.nfc.NdefRecord; -import android.nfc.NfcAdapter; -import android.nfc.NfcEvent; -import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.support.v7.view.ActionMode; @@ -75,6 +73,7 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); initializeCommonFields(); + AndroidBeam.disable(this); } @Override @@ -96,9 +95,9 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs return super.onOptionsItemSelected(item); } - public void onResume(final Subscription resumeSubscription) { + public void onResume(final Subscription... resumeSubscriptions) { super.onResume(); - this.resumeSubscription = resumeSubscription; + this.resumeSubscription = Subscriptions.from(resumeSubscriptions); } @Override @@ -203,34 +202,21 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs } } - // Do not support older devices than Android 4.0 - // Although there even are 2.3 devices (Nexus S) - // these are so few that we don't want to deal with the older (non Android Beam) API - - public interface ActivitySharingInterface { - /** Return an URL that represent the current activity for sharing or null for no sharing. */ - public String getAndroidBeamUri(); - } - - protected void initializeAndroidBeam(final ActivitySharingInterface sharingInterface) { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - initializeICSAndroidBeam(sharingInterface); + protected void setCacheTitleBar(@Nullable final String geocode, @Nullable final String name, @Nullable final CacheType type) { + if (StringUtils.isNotBlank(name)) { + setTitle(StringUtils.isNotBlank(geocode) ? name + " (" + geocode + ")" : name); + } else { + setTitle(StringUtils.isNotBlank(geocode) ? geocode : res.getString(R.string.cache)); } - } - - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - protected void initializeICSAndroidBeam(final ActivitySharingInterface sharingInterface) { - final NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); - if (nfcAdapter == null) { - return; + if (type != null) { + getSupportActionBar().setIcon(getResources().getDrawable(type.markerId)); + } else { + getSupportActionBar().setIcon(android.R.color.transparent); } - nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() { - @Override - public NdefMessage createNdefMessage(final NfcEvent event) { - final String uri = sharingInterface.getAndroidBeamUri(); - return uri != null ? new NdefMessage(new NdefRecord[]{NdefRecord.createUri(uri)}) : null; - } - }, this); + } + protected void setCacheTitleBar(final @NonNull Geocache cache) { + setCacheTitleBar(cache.getGeocode(), cache.getName(), cache.getType()); } + } diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java index d7482c3..86ca98f 100644 --- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java @@ -1,6 +1,7 @@ package cgeo.geocaching.activity; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.network.AndroidBeam; import android.content.res.Resources; import android.os.Bundle; @@ -48,6 +49,7 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme initializeCommonFields(); initUpAction(); + AndroidBeam.disable(this); } protected void initUpAction() { diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java index 64186a0..11a5436 100644 --- a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java @@ -68,14 +68,12 @@ public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends /** * Returns a validated view. * - * @return */ public View getDispatchedView(final ViewGroup parentView); /** * Returns a (maybe cached) view. * - * @return */ public View getView(final ViewGroup parentView); diff --git a/main/src/cgeo/geocaching/activity/ActionBarListActivity.java b/main/src/cgeo/geocaching/activity/ActionBarListActivity.java index 07c7ec3..a2d3ddf 100644 --- a/main/src/cgeo/geocaching/activity/ActionBarListActivity.java +++ b/main/src/cgeo/geocaching/activity/ActionBarListActivity.java @@ -18,12 +18,12 @@ public class ActionBarListActivity extends ActionBarActivity { return mListView; } - protected void setListAdapter(ListAdapter adapter) { + protected void setListAdapter(final ListAdapter adapter) { getListView().setAdapter(adapter); } protected ListAdapter getListAdapter() { - ListAdapter adapter = getListView().getAdapter(); + final ListAdapter adapter = getListView().getAdapter(); if (adapter instanceof HeaderViewListAdapter) { return ((HeaderViewListAdapter)adapter).getWrappedAdapter(); } diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java index 28042b0..01fc62e 100644 --- a/main/src/cgeo/geocaching/activity/ActivityMixin.java +++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java @@ -1,11 +1,14 @@ package cgeo.geocaching.activity; +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.MainActivity; import cgeo.geocaching.R; import cgeo.geocaching.settings.Settings; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Intent; import android.os.Build.VERSION; @@ -111,10 +114,15 @@ public final class ActivityMixin { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } if (Settings.useHardwareAcceleration()) { - window.setFlags(LayoutParams.FLAG_HARDWARE_ACCELERATED, LayoutParams.FLAG_HARDWARE_ACCELERATED); + enableHardwareAcceleration(window); } } + @TargetApi(VERSION_CODES.HONEYCOMB) + private static void enableHardwareAcceleration(final Window window) { + window.addFlags(LayoutParams.FLAG_HARDWARE_ACCELERATED); + } + public static void invalidateOptionsMenu(final Activity activity) { if (activity instanceof ActionBarActivity) { ((ActionBarActivity) activity).supportInvalidateOptionsMenu(); @@ -127,8 +135,6 @@ public final class ActivityMixin { /** * insert text into the EditText at the current cursor position * - * @param editText - * @param insertText * @param moveCursor * place the cursor after the inserted text */ @@ -139,7 +145,7 @@ public final class ActivityMixin { final int end = Math.max(selectionStart, selectionEnd); final String content = editText.getText().toString(); - String completeText; + final String completeText; if (start > 0 && !Character.isWhitespace(content.charAt(start - 1))) { completeText = " " + insertText; } else { @@ -152,13 +158,18 @@ public final class ActivityMixin { } public static boolean navigateUp(@NonNull final Activity activity) { - // see http://developer.android.com/training/implementing-navigation/ancestral.html - final Intent upIntent = NavUtils.getParentActivityIntent(activity); - if (upIntent == null) { + // first check if there is a parent declared in the manifest + Intent upIntent = NavUtils.getParentActivityIntent(activity); + // if there is no parent, and if this was not a new task, then just go back to simulate going to a parent + if (upIntent == null && !activity.isTaskRoot()) { activity.finish(); return true; } - if (NavUtils.shouldUpRecreateTask(activity, upIntent)) { + // use the main activity, if there was no back stack and no manifest based parent + if (upIntent == null) { + upIntent = new Intent(CgeoApplication.getInstance(), MainActivity.class); + } + if (NavUtils.shouldUpRecreateTask(activity, upIntent) || activity.isTaskRoot()) { // This activity is NOT part of this app's task, so create a new task // when navigating up, with a synthesized back stack. TaskStackBuilder.create(activity) @@ -175,7 +186,7 @@ public final class ActivityMixin { } public static void presentShowcase(final IAbstractActivity activity) { - if (VERSION.SDK_INT < 11) { + if (VERSION.SDK_INT < 14) { return; } final ShowcaseViewBuilder builder = activity.getShowcase(); diff --git a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/activity/OAuthAuthorizationActivity.java index eb56f0b..2dfac5b 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/activity/OAuthAuthorizationActivity.java @@ -1,13 +1,17 @@ -package cgeo.geocaching.network; +package cgeo.geocaching.activity; import butterknife.InjectView; import cgeo.geocaching.Intents; import cgeo.geocaching.R; -import cgeo.geocaching.activity.AbstractActivity; +import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.OAuth; +import cgeo.geocaching.network.OAuthTokens; +import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.BundleUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; +import cgeo.geocaching.utils.RxUtils; import ch.boye.httpclientandroidlib.HttpResponse; import ch.boye.httpclientandroidlib.ParseException; @@ -19,6 +23,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import rx.functions.Action0; + import android.app.ProgressDialog; import android.content.Intent; import android.net.Uri; @@ -40,6 +46,8 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private static final int STATUS_ERROR = 0; private static final int STATUS_SUCCESS = 1; private static final int STATUS_ERROR_EXT_MSG = 2; + private static final Pattern PARAMS_PATTERN_1 = Pattern.compile("oauth_token=([\\w_.-]+)"); + private static final Pattern PARAMS_PATTERN_2 = Pattern.compile("oauth_token_secret=([\\w_.-]+)"); @NonNull private String host = StringUtils.EMPTY; @NonNull private String pathRequest = StringUtils.EMPTY; @@ -51,18 +59,16 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull private String callback = StringUtils.EMPTY; private String OAtoken = null; private String OAtokenSecret = null; - private final Pattern paramsPattern1 = Pattern.compile("oauth_token=([a-zA-Z0-9\\-\\_.]+)"); - private final Pattern paramsPattern2 = Pattern.compile("oauth_token_secret=([a-zA-Z0-9\\-\\_.]+)"); @InjectView(R.id.start) protected Button startButton; @InjectView(R.id.auth_1) protected TextView auth_1; @InjectView(R.id.auth_2) protected TextView auth_2; private ProgressDialog requestTokenDialog = null; private ProgressDialog changeTokensDialog = null; - private Handler requestTokenHandler = new Handler() { + private final Handler requestTokenHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (requestTokenDialog != null && requestTokenDialog.isShowing()) { requestTokenDialog.dismiss(); } @@ -85,10 +91,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { }; - private Handler changeTokensHandler = new Handler() { + private final Handler changeTokensHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (changeTokensDialog != null && changeTokensDialog.isShowing()) { changeTokensDialog.dismiss(); } @@ -105,10 +111,10 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { }; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.authorization_activity); - Bundle extras = getIntent().getExtras(); + final Bundle extras = getIntent().getExtras(); if (extras != null) { host = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_HOST, host); pathRequest = BundleUtils.getString(extras, Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); @@ -125,7 +131,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { auth_1.setText(getAuthExplainShort()); auth_2.setText(getAuthExplainLong()); - ImmutablePair<String, String> tempToken = getTempTokens(); + final ImmutablePair<String, String> tempToken = getTempTokens(); OAtoken = tempToken.left; OAtokenSecret = tempToken.right; @@ -167,7 +173,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final Parameters params = new Parameters(); params.put("oauth_callback", callback); final String method = "GET"; - OAuth.signOAuth(host, pathRequest, method, https, params, null, null, consumerKey, consumerSecret); + OAuth.signOAuth(host, pathRequest, method, https, params, new OAuthTokens(null, null), consumerKey, consumerSecret); final HttpResponse response = Network.getRequest(getUrlPrefix() + host + pathRequest, params); if (Network.isSuccess(response)) { @@ -176,11 +182,11 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { int status = STATUS_ERROR; if (StringUtils.isNotBlank(line)) { assert line != null; - final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(PARAMS_PATTERN_1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(PARAMS_PATTERN_2, line); if (paramsMatcher2.find()) { OAtokenSecret = paramsMatcher2.group(1); } @@ -193,9 +199,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser)); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getUrlPrefix() + host + pathAuthorize + "?" + encodedParams))); status = STATUS_SUCCESS; - } catch (ParseException e) { - Log.e("OAuthAuthorizationActivity.requestToken", e); - } catch (IOException e) { + } catch (ParseException | IOException e) { Log.e("OAuthAuthorizationActivity.requestToken", e); } } @@ -221,17 +225,17 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { final Parameters params = new Parameters("oauth_verifier", verifier); final String method = "POST"; - OAuth.signOAuth(host, pathAccess, method, https, params, OAtoken, OAtokenSecret, consumerKey, consumerSecret); + OAuth.signOAuth(host, pathAccess, method, https, params, new OAuthTokens(OAtoken, OAtokenSecret), consumerKey, consumerSecret); final String line = StringUtils.defaultString(Network.getResponseData(Network.postRequest(getUrlPrefix() + host + pathAccess, params))); OAtoken = ""; OAtokenSecret = ""; - final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line); + final MatcherWrapper paramsMatcher1 = new MatcherWrapper(PARAMS_PATTERN_1, line); if (paramsMatcher1.find()) { OAtoken = paramsMatcher1.group(1); } - final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line); + final MatcherWrapper paramsMatcher2 = new MatcherWrapper(PARAMS_PATTERN_2, line); if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) { OAtokenSecret = paramsMatcher2.group(1); } @@ -244,7 +248,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { setTokens(OAtoken, OAtokenSecret, true); status = AUTHENTICATED; } - } catch (Exception e) { + } catch (final Exception e) { Log.e("OAuthAuthorizationActivity.changeToken", e); } @@ -258,7 +262,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { private class StartListener implements View.OnClickListener { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { if (requestTokenDialog == null) { requestTokenDialog = new ProgressDialog(OAuthAuthorizationActivity.this); requestTokenDialog.setCancelable(false); @@ -270,13 +274,12 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { startButton.setOnClickListener(null); setTempTokens(null, null); - (new Thread() { - + RxUtils.networkScheduler.createWorker().schedule(new Action0() { @Override - public void run() { + public void call() { requestToken(); } - }).start(); + }); } } @@ -288,13 +291,12 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { } changeTokensDialog.show(); - (new Thread() { - + RxUtils.networkScheduler.createWorker().schedule(new Action0() { @Override - public void run() { + public void call() { changeToken(verifier); } - }).start(); + }); } protected abstract ImmutablePair<String, String> getTempTokens(); @@ -333,7 +335,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { * @return String with a more detailed error message (user-facing, localized), can be empty */ @SuppressWarnings("static-method") - protected String getExtendedErrorMsg(HttpResponse response) { + protected String getExtendedErrorMsg(final HttpResponse response) { return StringUtils.EMPTY; } @@ -363,14 +365,14 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { @NonNull public final String consumerSecret; @NonNull public final String callback; - public OAuthParameters(@NonNull String host, - @NonNull String pathRequest, - @NonNull String pathAuthorize, - @NonNull String pathAccess, - boolean https, - @NonNull String consumerKey, - @NonNull String consumerSecret, - @NonNull String callback) { + public OAuthParameters(@NonNull final String host, + @NonNull final String pathRequest, + @NonNull final String pathAuthorize, + @NonNull final String pathAccess, + final boolean https, + @NonNull final String consumerKey, + @NonNull final String consumerSecret, + @NonNull final String callback) { this.host = host; this.pathRequest = pathRequest; this.pathAuthorize = pathAuthorize; @@ -381,7 +383,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActivity { this.callback = callback; } - public void setOAuthExtras(Intent intent) { + public void setOAuthExtras(final Intent intent) { if (intent != null) { intent.putExtra(Intents.EXTRA_OAUTH_HOST, host); intent.putExtra(Intents.EXTRA_OAUTH_PATH_REQUEST, pathRequest); diff --git a/main/src/cgeo/geocaching/activity/Progress.java b/main/src/cgeo/geocaching/activity/Progress.java index 8ee88a7..e87eaa6 100644 --- a/main/src/cgeo/geocaching/activity/Progress.java +++ b/main/src/cgeo/geocaching/activity/Progress.java @@ -19,7 +19,7 @@ public class Progress { private int progressDivider = 1; final private boolean hideAbsolute; - public Progress(boolean hideAbsolute) { + public Progress(final boolean hideAbsolute) { this.hideAbsolute = hideAbsolute; } diff --git a/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java b/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java index 04f096d..86f5302 100644 --- a/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java +++ b/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java @@ -29,7 +29,6 @@ public class ShowcaseViewBuilder extends Builder { /** * Use the hash of the title for the single shot remembering * - * @param resId */ private void setSingleshot(final CharSequence title) { super.singleShot(title.hashCode()); diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java index 494e245..3bc7f71 100644 --- a/main/src/cgeo/geocaching/apps/AbstractApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractApp.java @@ -5,28 +5,31 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.utils.ProcessUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import android.content.Intent; public abstract class AbstractApp implements App { - private final String packageName; - private final String intent; + @Nullable private final String packageName; + @Nullable private final String intent; + @NonNull private final String name; /** * a unique id, defined in res/values/ids.xml */ private final int id; - protected AbstractApp(final String name, final int id, final String intent, - final String packageName) { + protected AbstractApp(@NonNull final String name, final int id, @Nullable final String intent, + @Nullable final String packageName) { this.name = name; this.id = id; this.intent = intent; this.packageName = packageName; } - protected AbstractApp(final String name, final int id, final String intent) { + protected AbstractApp(@NonNull final String name, final int id, @Nullable final String intent) { this(name, id, intent, null); } @@ -35,9 +38,14 @@ public abstract class AbstractApp implements App { if (StringUtils.isNotEmpty(packageName) && ProcessUtils.isLaunchable(packageName)) { return true; } + if (intent == null) { + return false; + } + assert intent != null; // eclipse issue return ProcessUtils.isIntentAvailable(intent); } + @Nullable protected Intent getLaunchIntent() { return ProcessUtils.getLaunchIntent(packageName); } @@ -48,6 +56,7 @@ public abstract class AbstractApp implements App { } @Override + @NonNull public String getName() { return name; } @@ -57,12 +66,12 @@ public abstract class AbstractApp implements App { return id; } - protected static String getString(int ressourceId) { + protected static String getString(final int ressourceId) { return CgeoApplication.getInstance().getString(ressourceId); } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache != null; } } diff --git a/main/src/cgeo/geocaching/apps/AbstractAppFactory.java b/main/src/cgeo/geocaching/apps/AbstractAppFactory.java deleted file mode 100644 index 945f7d6..0000000 --- a/main/src/cgeo/geocaching/apps/AbstractAppFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package cgeo.geocaching.apps; - -import android.view.MenuItem; - -public abstract class AbstractAppFactory { - - protected static App getAppFromMenuItem(MenuItem item, final App[] availableApps) { - final int id = item.getItemId(); - for (App app : availableApps) { - if (app.getId() == id) { - return app; - } - } - return null; - } -} diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java index baf36a4..dfd148d 100644 --- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java @@ -8,6 +8,7 @@ import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.utils.SynchronizedDateFormat; +import menion.android.locus.LocusDataStorageProvider; import menion.android.locus.addon.publiclib.DisplayData; import menion.android.locus.addon.publiclib.LocusUtils; import menion.android.locus.addon.publiclib.geoData.Point; @@ -15,6 +16,9 @@ import menion.android.locus.addon.publiclib.geoData.PointGeocachingData; import menion.android.locus.addon.publiclib.geoData.PointGeocachingDataWaypoint; import menion.android.locus.addon.publiclib.geoData.PointsData; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import android.app.Activity; import android.location.Location; @@ -31,7 +35,7 @@ import java.util.Locale; public abstract class AbstractLocusApp extends AbstractApp { private static final SynchronizedDateFormat ISO8601DATE = new SynchronizedDateFormat("yyyy-MM-dd'T'", Locale.US); - protected AbstractLocusApp(final String text, int id, final String intent) { + protected AbstractLocusApp(@NonNull final String text, final int id, @NonNull final String intent) { super(text, id, intent); } @@ -47,7 +51,6 @@ public abstract class AbstractLocusApp extends AbstractApp { * which caches/waypoints to show * @param withCacheWaypoints * Whether to give waypoints of caches to Locus or not - * @param activity */ protected static boolean showInLocus(final List<?> objectsToShow, final boolean withCacheWaypoints, final boolean export, final Activity activity) { @@ -57,7 +60,7 @@ public abstract class AbstractLocusApp extends AbstractApp { final boolean withCacheDetails = objectsToShow.size() < 200; final PointsData pd = new PointsData("c:geo"); - for (Object o : objectsToShow) { + for (final Object o : objectsToShow) { Point p = null; // get icon and Point if (o instanceof Geocache) { @@ -90,7 +93,6 @@ public abstract class AbstractLocusApp extends AbstractApp { /** * This method constructs a <code>Point</code> for displaying in Locus * - * @param cache * @param withWaypoints * whether to give waypoints to Locus or not * @param withCacheDetails @@ -98,7 +100,8 @@ public abstract class AbstractLocusApp extends AbstractApp { * should be false for all if more then 200 Caches are transferred * @return null, when the <code>Point</code> could not be constructed */ - private static Point getCachePoint(Geocache cache, boolean withWaypoints, boolean withCacheDetails) { + @Nullable + private static Point getCachePoint(final Geocache cache, final boolean withWaypoints, final boolean withCacheDetails) { if (cache == null || cache.getCoords() == null) { return null; } @@ -141,19 +144,24 @@ public abstract class AbstractLocusApp extends AbstractApp { if (withWaypoints && cache.hasWaypoints()) { pg.waypoints = new ArrayList<>(); - for (Waypoint waypoint : cache.getWaypoints()) { - if (waypoint == null || waypoint.getCoords() == null) { + for (final Waypoint waypoint : cache.getWaypoints()) { + if (waypoint == null) { continue; } - PointGeocachingDataWaypoint wp = new PointGeocachingDataWaypoint(); - wp.code = waypoint.getGeocode(); + + final PointGeocachingDataWaypoint wp = new PointGeocachingDataWaypoint(); + wp.code = waypoint.getLookup(); wp.name = waypoint.getName(); - String locusWpId = toLocusWaypoint(waypoint.getWaypointType()); + wp.description = waypoint.getNote(); + final String locusWpId = toLocusWaypoint(waypoint.getWaypointType()); if (locusWpId != null) { wp.type = locusWpId; } - wp.lat = waypoint.getCoords().getLatitude(); - wp.lon = waypoint.getCoords().getLongitude(); + + if (waypoint.getCoords() != null) { + wp.lat = waypoint.getCoords().getLatitude(); + wp.lon = waypoint.getCoords().getLongitude(); + } pg.waypoints.add(wp); } } @@ -174,10 +182,10 @@ public abstract class AbstractLocusApp extends AbstractApp { /** * This method constructs a <code>Point</code> for displaying in Locus * - * @param waypoint * @return null, when the <code>Point</code> could not be constructed */ - private static Point getWaypointPoint(Waypoint waypoint) { + @Nullable + private static Point getWaypointPoint(final Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { return null; } @@ -248,6 +256,7 @@ public abstract class AbstractLocusApp extends AbstractApp { } } + @Nullable private static String toLocusWaypoint(final WaypointType wt) { switch (wt) { case FINAL: @@ -268,5 +277,4 @@ public abstract class AbstractLocusApp extends AbstractApp { return null; } } - } diff --git a/main/src/cgeo/geocaching/apps/App.java b/main/src/cgeo/geocaching/apps/App.java index 7e70581..1383809 100644 --- a/main/src/cgeo/geocaching/apps/App.java +++ b/main/src/cgeo/geocaching/apps/App.java @@ -2,6 +2,8 @@ package cgeo.geocaching.apps; import cgeo.geocaching.Geocache; +import org.eclipse.jdt.annotation.NonNull; + public interface App { public boolean isInstalled(); @@ -10,6 +12,7 @@ public interface App { */ public boolean isUsableAsDefaultNavigationApp(); + @NonNull public String getName(); /** @@ -20,8 +23,6 @@ public interface App { /** * Whether or not the app can be used with the given cache (may depend on properties of the cache). * - * @param cache - * @return */ boolean isEnabled(final Geocache cache); } diff --git a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java index c4f2723..4e542b8 100644 --- a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java +++ b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java @@ -4,17 +4,19 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.apps.AbstractApp; import cgeo.geocaching.apps.cache.navi.CacheNavigationApp; +import org.eclipse.jdt.annotation.NonNull; + import android.app.Activity; import android.content.Intent; abstract class AbstractGeneralApp extends AbstractApp implements CacheNavigationApp { - protected AbstractGeneralApp(final String name, final int id, final String packageName) { + protected AbstractGeneralApp(@NonNull final String name, final int id, @NonNull final String packageName) { super(name, id, null, packageName); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { final Intent intent = getLaunchIntent(); if (intent != null) { intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); diff --git a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java index b2a2cad..cdfbceb 100644 --- a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java +++ b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java @@ -21,16 +21,16 @@ public class WhereYouGoApp extends AbstractGeneralApp { } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache.getType() == CacheType.WHERIGO && StringUtils.isNotEmpty(getWhereIGoUrl(cache)); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getWhereIGoUrl(cache)))); } - protected static String getWhereIGoUrl(Geocache cache) { + protected static String getWhereIGoUrl(final Geocache cache) { return TextUtils.getMatch(cache.getDescription(), PATTERN_CARTRIDGE, null); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java index ec9705c..0bf2c1c 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java @@ -5,7 +5,9 @@ import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; + +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.content.Intent; @@ -15,20 +17,20 @@ import android.content.Intent; */ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp { - protected AbstractPointNavigationApp(final String name, final int id, final String intent) { + protected AbstractPointNavigationApp(@NonNull final String name, final int id, final String intent) { super(name, id, intent); } - protected AbstractPointNavigationApp(final String name, final int id, final String intent, final String packageName) { + protected AbstractPointNavigationApp(@NonNull final String name, final int id, final String intent, final String packageName) { super(name, id, intent, packageName); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { navigateWithNullCheck(activity, cache.getCoords()); } - private void navigateWithNullCheck(Activity activity, final Geopoint coords) { + private void navigateWithNullCheck(final Activity activity, final Geopoint coords) { if (coords != null) { navigate(activity, coords); } else { @@ -37,17 +39,17 @@ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNa } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { navigateWithNullCheck(activity, waypoint.getCoords()); } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache.getCoords() != null; } @Override - public boolean isEnabled(Waypoint waypoint) { + public boolean isEnabled(final Waypoint waypoint) { return waypoint.getCoords() != null; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractRadarApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractRadarApp.java index 6c6ffda..00b0954 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractRadarApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractRadarApp.java @@ -2,12 +2,15 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.Geocache; import cgeo.geocaching.Waypoint; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.app.Activity; import android.content.Intent; -public abstract class AbstractRadarApp extends AbstractPointNavigationApp { +abstract class AbstractRadarApp extends AbstractPointNavigationApp { + + protected static final String RADAR_EXTRA_LONGITUDE = "longitude"; + protected static final String RADAR_EXTRA_LATITUDE = "latitude"; private final String intentAction; diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java index a2a5803..700c8aa 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java @@ -11,11 +11,12 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractApp; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp { - protected AbstractStaticMapsApp(final String name, final int id) { + protected AbstractStaticMapsApp(@NonNull final String name, final int id) { super(name, id, null); } @@ -29,11 +30,11 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat return false; } - protected static boolean hasStaticMap(Waypoint waypoint) { + protected static boolean hasStaticMap(final Waypoint waypoint) { if (waypoint==null) { return false; } - String geocode = waypoint.getGeocode(); + final String geocode = waypoint.getGeocode(); if (StringUtils.isNotEmpty(geocode) && DataStore.isOffline(geocode, null)) { return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint); } @@ -49,7 +50,7 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat } final String geocode = StringUtils.upperCase(logable.getGeocode()); - StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download); + final StaticMapsActivity_.IntentBuilder_ builder = StaticMapsActivity_.intent(activity).geocode(geocode).download(download); if (waypoint != null) { builder.waypointId(waypoint.getId()); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AndroidWearApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AndroidWearApp.java new file mode 100644 index 0000000..5abe2fc --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cache/navi/AndroidWearApp.java @@ -0,0 +1,52 @@ +package cgeo.geocaching.apps.cache.navi; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.Intents; +import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.utils.ProcessUtils; + +import android.app.Activity; +import android.content.Intent; + +/** + * For use with any Android Wear geocaching apps which can handle the intent action below. + */ +class AndroidWearApp extends AbstractPointNavigationApp { + private static final String INTENT_ACTION = "cgeo.geocaching.wear.NAVIGATE_TO"; + + public AndroidWearApp() { + super(getString(R.string.cache_menu_android_wear), R.id.cache_app_android_wear, INTENT_ACTION, null); + } + + @Override + public boolean isInstalled() { + return ProcessUtils.isIntentAvailable(INTENT_ACTION); + } + + @Override + public void navigate(final Activity activity, final Geopoint coords) { + navigate(activity, null, null, coords); + } + + @Override + public void navigate(final Activity activity, final Geocache cache) { + navigate(activity, cache.getName(), cache.getGeocode(), cache.getCoords()); + } + + @Override + public void navigate(final Activity activity, final Waypoint waypoint) { + navigate(activity, waypoint.getName(), waypoint.getGeocode(), waypoint.getCoords()); + } + + private static void navigate(final Activity activity, final String destName, + final String destCode, final Geopoint coords) { + final Intent launchIntent = new Intent(INTENT_ACTION); + launchIntent.putExtra(Intents.EXTRA_NAME, destName) + .putExtra(Intents.EXTRA_GEOCODE, destCode) + .putExtra(Intents.EXTRA_LATITUDE, coords.getLatitude()) + .putExtra(Intents.EXTRA_LONGITUDE, coords.getLongitude()); + activity.startService(launchIntent); + } +} diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java index d47bdc0..7387e94 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java @@ -11,7 +11,4 @@ import android.app.Activity; */ public interface CacheNavigationApp extends App { void navigate(final Activity activity, final Geocache cache); - - @Override - boolean isEnabled(final Geocache cache); }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java index 03d2220..8e1e4cf 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java @@ -4,7 +4,7 @@ import cgeo.geocaching.CompassActivity; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.app.Activity; @@ -20,19 +20,18 @@ class CompassApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint coords) { - CompassActivity.startActivity(activity, getString(R.string.navigation_direct_navigation), getString(R.string.navigation_target), coords, null); + public void navigate(final Activity activity, final Geopoint coords) { + CompassActivity.startActivityPoint(activity, coords, getString(R.string.navigation_direct_navigation)); } @Override - public void navigate(Activity activity, Waypoint waypoint) { - CompassActivity.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null, - waypoint.getWaypointType().getL10n()); + public void navigate(final Activity activity, final Waypoint waypoint) { + CompassActivity.startActivityWaypoint(activity, waypoint); } @Override - public void navigate(Activity activity, Geocache cache) { - CompassActivity.startActivity(activity, cache); + public void navigate(final Activity activity, final Geocache cache) { + CompassActivity.startActivityCache(activity, cache); } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java index fe4fd5d..5031dd8 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java @@ -1,6 +1,6 @@ package cgeo.geocaching.apps.cache.navi; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.app.Activity; @@ -8,6 +8,6 @@ import android.app.Activity; * interface for navigation to a coordinate. This one cannot be enabled/disabled. * */ -public interface GeopointNavigationApp { +interface GeopointNavigationApp { void navigate(final Activity activity, final Geopoint coords); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java index 6c184ce..c12b4ca 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java @@ -4,9 +4,9 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; -import cgeo.geocaching.geopoint.GeopointFormatter.Format; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; +import cgeo.geocaching.location.GeopointFormatter.Format; import cgeo.geocaching.utils.Log; import android.app.Activity; @@ -25,20 +25,20 @@ class GoogleMapsApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint point) { + public void navigate(final Activity activity, final Geopoint point) { navigate(activity, point, activity.getString(R.string.waypoint)); } - private static void navigate(Activity activity, Geopoint point, String label) { + private static void navigate(final Activity activity, final Geopoint point, final String label) { try { - String latitude = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, point); - String longitude = GeopointFormatter.format(Format.LON_DECDEGREE_RAW, point); + final String latitude = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, point); + final String longitude = GeopointFormatter.format(Format.LON_DECDEGREE_RAW, point); final String geoLocation = "geo:" + latitude + "," + longitude; final String query = latitude + "," + longitude + "(" + label + ")"; final String uriString = geoLocation + "?q=" + Uri.encode(query); activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(uriString))); return; - } catch (RuntimeException e) { + } catch (final RuntimeException ignored) { // nothing } Log.i("GoogleMapsApp.navigate: No maps application available."); @@ -47,12 +47,12 @@ class GoogleMapsApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { navigate(activity, cache.getCoords(), cache.getName()); } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { navigate(activity, waypoint.getCoords(), waypoint.getName()); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java index 4924786..d14fca4 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java @@ -1,17 +1,17 @@ package cgeo.geocaching.apps.cache.navi; -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.MapProviderFactory; +import cgeo.geocaching.sensors.GeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.utils.Log; import android.app.Activity; import android.content.Intent; import android.net.Uri; -public class GoogleMapsDirectionApp extends AbstractPointNavigationApp { +class GoogleMapsDirectionApp extends AbstractPointNavigationApp { protected GoogleMapsDirectionApp() { super(getString(R.string.cache_menu_maps_directions), R.id.cache_app_google_maps_direction, null); @@ -23,23 +23,15 @@ public class GoogleMapsDirectionApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint coords) { + public void navigate(final Activity activity, final Geopoint coords) { try { - IGeoData geo = CgeoApplication.getInstance().currentGeo(); - final Geopoint coordsNow = geo == null ? null : geo.getCoords(); - - if (coordsNow != null) { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri - .parse("http://maps.google.com/maps?f=d&saddr=" - + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + "&daddr=" - + coords.getLatitude() + "," + coords.getLongitude()))); - } else { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri - .parse("http://maps.google.com/maps?f=d&daddr=" - + coords.getLatitude() + "," + coords.getLongitude()))); - } - - } catch (Exception e) { + final GeoData geo = Sensors.getInstance().currentGeo(); + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri + .parse("http://maps.google.com/maps?f=d&saddr=" + + geo.getCoords().getLatitude() + "," + geo.getCoords().getLongitude() + "&daddr=" + + coords.getLatitude() + "," + coords.getLongitude()))); + + } catch (final Exception e) { Log.i("GoogleMapsDirectionApp: application not available.", e); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java index 902eebf..0e6e97a 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java @@ -1,7 +1,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.Log; import android.app.Activity; @@ -12,7 +12,7 @@ abstract class GoogleNavigationApp extends AbstractPointNavigationApp { private final String mode; - protected GoogleNavigationApp(final int nameResourceId, final int id, final String mode) { + private GoogleNavigationApp(final int nameResourceId, final int id, final String mode) { super(getString(nameResourceId), id, null); this.mode = mode; } @@ -23,7 +23,7 @@ abstract class GoogleNavigationApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint coords) { + public void navigate(final Activity activity, final Geopoint coords) { try { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri .parse("google.navigation:ll=" + coords.getLatitude() + "," diff --git a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java index 540b025..03c6dc1 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java @@ -4,7 +4,7 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.CGeoMap; import android.app.Activity; @@ -21,17 +21,17 @@ class InternalMap extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint coords) { + public void navigate(final Activity activity, final Geopoint coords) { CGeoMap.startActivityCoords(activity, coords, WaypointType.WAYPOINT, null); } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { CGeoMap.startActivityCoords(activity, waypoint.getCoords(), waypoint.getWaypointType(), waypoint.getName()); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { CGeoMap.startActivityGeoCode(activity, cache.getGeocode()); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java index b60d78a..61445c3 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java @@ -20,12 +20,12 @@ class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointN } @Override - public boolean isEnabled(Waypoint waypoint) { + public boolean isEnabled(final Waypoint waypoint) { return waypoint.getCoords() != null; } @Override - public boolean isEnabled(Geocache cache) { + public boolean isEnabled(final Geocache cache) { return cache.getCoords() != null; } @@ -35,12 +35,12 @@ class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointN * */ @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { showInLocus(Collections.singletonList(waypoint), true, false, activity); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { showInLocus(Collections.singletonList(cache), true, false, activity); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java b/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java index ea5aebb..9403dcd 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/MapsWithMeApp.java @@ -3,34 +3,34 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import com.mapswithme.maps.api.MapsWithMeApi; import android.app.Activity; -public class MapsWithMeApp extends AbstractPointNavigationApp { +class MapsWithMeApp extends AbstractPointNavigationApp { protected MapsWithMeApp() { super(getString(R.string.cache_menu_mapswithme), R.id.cache_app_mapswithme, null); } @Override - public void navigate(Activity activity, Geopoint coords) { + public void navigate(final Activity activity, final Geopoint coords) { navigate(activity, coords, getString(R.string.unknown)); } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { navigate(activity, cache.getCoords(), cache.getName()); } - private static void navigate(Activity activity, Geopoint coords, String label) { + private static void navigate(final Activity activity, final Geopoint coords, final String label) { MapsWithMeApi.showPointOnMap(activity, coords.getLatitude(), coords.getLongitude(), label); } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { navigate(activity, waypoint.getCoords(), waypoint.getName()); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java index c00723d..32eba7e 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java @@ -5,13 +5,12 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.apps.AbstractAppFactory; import cgeo.geocaching.apps.App; import cgeo.geocaching.apps.cache.WhereYouGoApp; import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationBikeApp; import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp; import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationWalkingApp; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import org.eclipse.jdt.annotation.Nullable; @@ -25,7 +24,11 @@ import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.List; -public final class NavigationAppFactory extends AbstractAppFactory { +public final class NavigationAppFactory { + + private NavigationAppFactory() { + // utility class + } public enum NavigationAppsEnum { /** The internal compass activity */ @@ -69,12 +72,16 @@ public final class NavigationAppFactory extends AbstractAppFactory { WHERE_YOU_GO(new WhereYouGoApp(), 16, R.string.pref_navigation_menu_where_you_go), PEBBLE(new PebbleApp(), 17, R.string.pref_navigation_menu_pebble), + ANDROID_WEAR(new AndroidWearApp(), 18, R.string.pref_navigation_menu_android_wear), MAPSWITHME(new MapsWithMeApp(), 22, R.string.pref_navigation_menu_mapswithme); NavigationAppsEnum(final App app, final int id, final int preferenceKey) { this.app = app; this.id = id; this.preferenceKey = preferenceKey; + if (preferenceKey == 0 || preferenceKey == -1) { + throw new IllegalStateException("Every navigation app must have a boolean preference in the settings to be enabled/disabled."); + } } /** @@ -109,10 +116,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Delegates to {@link #showNavigationMenu(Activity, cgeo.geocaching.Geocache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} with * <code>showInternalMap = true</code> and <code>showDefaultNavigation = false</code> * - * @param activity - * @param cache - * @param waypoint - * @param destination */ public static void showNavigationMenu(final Activity activity, final Geocache cache, final Waypoint waypoint, final Geopoint destination) { @@ -123,7 +126,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Specialized way to handle selection of navigation tool.<br /> * A dialog is created for tool selection and the selected tool is started afterwards. * - * @param activity * @param cache * may be <code>null</code> * @param waypoint @@ -188,9 +190,8 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Returns all installed navigation apps. * - * @return */ - public static List<NavigationAppsEnum> getInstalledNavigationApps() { + static List<NavigationAppsEnum> getInstalledNavigationApps() { final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<>(); for (final NavigationAppsEnum appEnum : NavigationAppsEnum.values()) { if (appEnum.app.isInstalled()) { @@ -203,7 +204,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * @return all navigation apps, which are installed and activated in the settings */ - public static List<NavigationAppsEnum> getActiveNavigationApps() { + static List<NavigationAppsEnum> getActiveNavigationApps() { final List<NavigationAppsEnum> activeApps = new ArrayList<>(); for (final NavigationAppsEnum appEnum : getInstalledNavigationApps()) { if (Settings.isUseNavigationApp(appEnum)) { @@ -216,7 +217,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Returns all installed navigation apps for default navigation. * - * @return */ public static List<NavigationAppsEnum> getInstalledDefaultNavigationApps() { final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<>(); @@ -232,10 +232,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { * Handles menu selections for menu entries created with * {@link #showNavigationMenu(Activity, Geocache, Waypoint, Geopoint)}. * - * @param item - * @param activity - * @param cache - * @return */ public static boolean onMenuItemSelected(final MenuItem item, final Activity activity, final Geocache cache) { final App menuItem = getAppFromMenuItem(item); @@ -278,10 +274,7 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Starts the default navigation tool if correctly set and installed or the compass app as default fallback. * - * @param defaultNavigation * - * @param activity - * @param cache */ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Geocache cache) { if (cache == null || cache.getCoords() == null) { @@ -302,8 +295,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Starts the default navigation tool if correctly set and installed or the compass app as default fallback. * - * @param activity - * @param waypoint */ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Waypoint waypoint) { if (waypoint == null || waypoint.getCoords() == null) { @@ -316,8 +307,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { /** * Starts the default navigation tool if correctly set and installed or the compass app as default fallback. * - * @param activity - * @param destination */ public static void startDefaultNavigationApplication(final int defaultNavigation, final Activity activity, final Geopoint destination) { if (destination == null) { diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java index 82883a2..43eaee3 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java @@ -3,6 +3,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.Geocache; import cgeo.geocaching.apps.App; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; +import cgeo.geocaching.ui.AbstractMenuActionProvider; import android.app.Activity; import android.content.Context; @@ -12,11 +13,13 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; import android.view.SubMenu; -import android.view.View; import java.util.List; -public class NavigationSelectionActionProvider extends ActionProvider { +/** + * Action provider listing all available navigation actions as sub menu. + */ +public class NavigationSelectionActionProvider extends AbstractMenuActionProvider { private Geocache geocache; private final Activity activity; @@ -26,17 +29,6 @@ public class NavigationSelectionActionProvider extends ActionProvider { activity = (Activity) context; } - @Override - public boolean hasSubMenu() { - return true; - } - - @Override - public View onCreateActionView() { - // must return null, otherwise the menu will not work - return null; - } - public void setTarget(final Geocache cache) { geocache = cache; } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java index 024bf37..9954382 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java @@ -1,7 +1,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.app.Activity; import android.content.Intent; @@ -17,7 +17,7 @@ class NavigonApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint point) { + public void navigate(final Activity activity, final Geopoint point) { final Intent intent = new Intent(INTENT); /* diff --git a/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java index 5d645f7..b3e21a3 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java @@ -1,13 +1,15 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.app.Activity; import android.content.Intent; class OruxMapsApp extends AbstractPointNavigationApp { + private static final String ORUXMAPS_EXTRA_LONGITUDE = "longitude"; + private static final String ORUXMAPS_EXTRA_LATITUDE = "latitude"; private static final String INTENT = "com.oruxmaps.VIEW_MAP_ONLINE"; OruxMapsApp() { @@ -15,10 +17,10 @@ class OruxMapsApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint point) { + public void navigate(final Activity activity, final Geopoint point) { final Intent intent = new Intent(INTENT); - intent.putExtra("latitude", point.getLatitude());//latitude, wgs84 datum - intent.putExtra("longitude", point.getLongitude());//longitude, wgs84 datum + intent.putExtra(ORUXMAPS_EXTRA_LATITUDE, point.getLatitude());//latitude, wgs84 datum + intent.putExtra(ORUXMAPS_EXTRA_LONGITUDE, point.getLongitude());//longitude, wgs84 datum activity.startActivity(intent); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/PebbleApp.java b/main/src/cgeo/geocaching/apps/cache/navi/PebbleApp.java index ac83085..f384192 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/PebbleApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/PebbleApp.java @@ -1,26 +1,26 @@ -package cgeo.geocaching.apps.cache.navi;
-
-import cgeo.geocaching.R;
-import cgeo.geocaching.geopoint.Geopoint;
-
-import android.content.Intent;
-
-/**
- * Application for communication with the Pebble watch.
- *
- */
-class PebbleApp extends AbstractRadarApp {
-
- private static final String INTENT = "com.webmajstr.pebble_gc.NAVIGATE_TO";
- private static final String PACKAGE_NAME = "com.webmajstr.pebble_gc";
-
- PebbleApp() {
- super(getString(R.string.cache_menu_pebble), R.id.cache_app_pebble, INTENT, PACKAGE_NAME);
- }
-
- @Override
- protected void addCoordinates(final Intent intent, final Geopoint coords) {
- intent.putExtra("latitude", coords.getLatitude());
- intent.putExtra("longitude", coords.getLongitude());
- }
+package cgeo.geocaching.apps.cache.navi; + +import cgeo.geocaching.R; +import cgeo.geocaching.location.Geopoint; + +import android.content.Intent; + +/** + * Application for communication with the Pebble watch. + * + */ +class PebbleApp extends AbstractRadarApp { + + private static final String INTENT = "com.webmajstr.pebble_gc.NAVIGATE_TO"; + private static final String PACKAGE_NAME = "com.webmajstr.pebble_gc"; + + PebbleApp() { + super(getString(R.string.cache_menu_pebble), R.id.cache_app_pebble, INTENT, PACKAGE_NAME); + } + + @Override + protected void addCoordinates(final Intent intent, final Geopoint coords) { + intent.putExtra(RADAR_EXTRA_LATITUDE, coords.getLatitude()); + intent.putExtra(RADAR_EXTRA_LONGITUDE, coords.getLongitude()); + } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java index 4dbb46c..1eefdec 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java @@ -3,8 +3,8 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter.Format; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter.Format; import android.app.Activity; import android.content.Intent; @@ -20,11 +20,11 @@ class RMapsApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Waypoint waypoint) { + public void navigate(final Activity activity, final Waypoint waypoint) { navigate(activity, waypoint.getCoords(), waypoint.getLookup(), waypoint.getName()); } - private static void navigate(Activity activity, Geopoint coords, String code, String name) { + private static void navigate(final Activity activity, final Geopoint coords, final String code, final String name) { final ArrayList<String> locations = new ArrayList<>(); locations.add(coords.format(Format.LAT_LON_DECDEGREE_COMMA) + ";" + code + ";" + name); final Intent intent = new Intent(INTENT); @@ -33,12 +33,12 @@ class RMapsApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geocache cache) { + public void navigate(final Activity activity, final Geocache cache) { navigate(activity, cache.getCoords(), cache.getGeocode(), cache.getName()); } @Override - public void navigate(Activity activity, Geopoint coords) { + public void navigate(final Activity activity, final Geopoint coords) { navigate(activity, coords, "", ""); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java index 41cf2d8..a26edc4 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java @@ -1,7 +1,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.content.Intent; @@ -16,8 +16,8 @@ class RadarApp extends AbstractRadarApp { @Override protected void addCoordinates(final Intent intent, final Geopoint coords) { - intent.putExtra("latitude", (float) coords.getLatitude()); - intent.putExtra("longitude", (float) coords.getLongitude()); + intent.putExtra(RADAR_EXTRA_LATITUDE, (float) coords.getLatitude()); + intent.putExtra(RADAR_EXTRA_LONGITUDE, (float) coords.getLongitude()); } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java index 7294a40..ca3aefe 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java @@ -3,7 +3,7 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.ProcessUtils; import android.app.Activity; @@ -26,11 +26,11 @@ class StreetviewApp extends AbstractPointNavigationApp { } @Override - public void navigate(Activity activity, Geopoint point) { + public void navigate(final Activity activity, final Geopoint point) { try { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("google.streetview:cbll=" + point.getLatitude() + "," + point.getLongitude()))); - } catch (final ActivityNotFoundException e) { + } catch (final ActivityNotFoundException ignored) { ActivityMixin.showToast(activity, CgeoApplication.getInstance().getString(R.string.err_application_no)); } } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java index 76b7f0e..391fa90 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/SygicNavigationApp.java @@ -1,7 +1,8 @@ package cgeo.geocaching.apps.cache.navi; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.utils.ProcessUtils; import android.app.Activity; import android.content.Intent; @@ -12,17 +13,26 @@ import android.net.Uri; * handler * */ -public class SygicNavigationApp extends AbstractPointNavigationApp { +class SygicNavigationApp extends AbstractPointNavigationApp { - private static final String PACKAGE = "com.sygic.aura"; + private static final String PACKAGE_NORMAL = "com.sygic.aura"; + /** + * there is a secondary edition of this app + */ + private static final String PACKAGE_VOUCHER = "com.sygic.aura_voucher"; SygicNavigationApp() { - super(getString(R.string.cache_menu_sygic), R.id.cache_app_sygic, null, PACKAGE); + super(getString(R.string.cache_menu_sygic), R.id.cache_app_sygic, null, PACKAGE_NORMAL); } @Override - public void navigate(Activity activity, Geopoint coords) { - String str = "http://com.sygic.aura/coordinate|" + coords.getLongitude() + "|" + coords.getLatitude() + "|show"; + public boolean isInstalled() { + return ProcessUtils.isLaunchable(PACKAGE_NORMAL) || ProcessUtils.isLaunchable(PACKAGE_VOUCHER); + } + + @Override + public void navigate(final Activity activity, final Geopoint coords) { + final String str = "http://com.sygic.aura/coordinate|" + coords.getLongitude() + "|" + coords.getLatitude() + "|show"; activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(str))); } diff --git a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java index c26ec3e..ba85a1d 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java @@ -8,7 +8,7 @@ import android.app.Activity; * interface for navigation to a waypoint * */ -public interface WaypointNavigationApp { +interface WaypointNavigationApp { void navigate(final Activity activity, final Waypoint waypoint); boolean isEnabled(final Waypoint waypoint); diff --git a/main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java index 6411758..d047d1a 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java +++ b/main/src/cgeo/geocaching/apps/cachelist/AbstractLocusCacheListApp.java @@ -14,9 +14,9 @@ import java.util.List; abstract class AbstractLocusCacheListApp extends AbstractLocusApp implements CacheListApp { - private boolean export; + private final boolean export; - public AbstractLocusCacheListApp(final int id, boolean export) { + public AbstractLocusCacheListApp(final int id, final boolean export) { super(getString(export ? R.string.caches_map_locus_export : R.string.caches_map_locus), id, Intent.ACTION_VIEW); this.export = export; } @@ -27,7 +27,7 @@ abstract class AbstractLocusCacheListApp extends AbstractLocusApp implements Cac * @see AbstractLocusApp#showInLocus */ @Override - public boolean invoke(List<Geocache> cacheList, Activity activity, final SearchResult search) { + public boolean invoke(final List<Geocache> cacheList, final Activity activity, final SearchResult search) { if (CollectionUtils.isEmpty(cacheList)) { return false; } diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java index 40c4d92..8beb5e4 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java @@ -8,7 +8,7 @@ import android.app.Activity; import java.util.List; -interface CacheListApp extends App { +public interface CacheListApp extends App { boolean invoke(final List<Geocache> caches, final Activity activity, final SearchResult search); diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java deleted file mode 100644 index 5886168..0000000 --- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java +++ /dev/null @@ -1,84 +0,0 @@ -package cgeo.geocaching.apps.cachelist; - -import cgeo.geocaching.Geocache; -import cgeo.geocaching.R; -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.apps.AbstractAppFactory; -import cgeo.geocaching.utils.Log; - -import android.app.Activity; -import android.content.res.Resources; -import android.view.Menu; -import android.view.MenuItem; -import android.view.SubMenu; - -import java.util.ArrayList; -import java.util.List; - -public final class CacheListAppFactory extends AbstractAppFactory { - private static class LazyHolder { - public static final CacheListApp[] apps = { - new InternalCacheListMap(), - new LocusShowCacheListApp(), - new LocusExportCacheListApp(), - new MapsWithMeCacheListApp() - }; - } - - /** - * @param menu - * @param activity - * @param res - */ - public static void addMenuItems(final Menu menu, final Activity activity, final Resources res) { - final List<CacheListApp> activeApps = getActiveApps(); - if (activeApps.isEmpty()) { - return; - } - if (activeApps.size() == 1) { - final MenuItem subItem = menu.findItem(R.id.menu_cache_list_app); - subItem.setVisible(true); - subItem.setTitle(activeApps.get(0).getName()); - } else { - final MenuItem subItem = menu.findItem(R.id.submenu_cache_list_app); - subItem.setVisible(true); - final SubMenu subMenu = subItem.getSubMenu(); - for (final CacheListApp app : activeApps) { - subMenu.add(0, app.getId(), 0, app.getName()); - } - } - } - - private static List<CacheListApp> getActiveApps() { - final List<CacheListApp> activeApps = new ArrayList<>(LazyHolder.apps.length); - for (final CacheListApp app : LazyHolder.apps) { - if (app.isInstalled()) { - activeApps.add(app); - } - } - return activeApps; - } - - public static boolean onMenuItemSelected(final MenuItem item, final List<Geocache> caches, final Activity activity, - final SearchResult search) { - CacheListApp app; - if (item.getItemId() == R.id.menu_cache_list_app) { - app = getActiveApps().get(0); - } - else { - app = (CacheListApp) getAppFromMenuItem(item, LazyHolder.apps); - } - if (app != null) { - try { - boolean result = app.invoke(caches, activity, search); - ActivityMixin.invalidateOptionsMenu(activity); - return result; - } catch (Exception e) { - Log.e("CacheListAppFactory.onMenuItemSelected", e); - } - } - return false; - } - -} diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java new file mode 100644 index 0000000..e8e81a8 --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApps.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.apps.cachelist; + +import java.util.ArrayList; +import java.util.List; + +public enum CacheListApps { + INTERNAL(new InternalCacheListMap()), + LOCUS_SHOW(new LocusShowCacheListApp()), + LOCUS_EXPORT(new LocusExportCacheListApp()), + MAPS_ME(new MapsWithMeCacheListApp()); + + private final CacheListApp app; + + private CacheListApps(final CacheListApp app) { + this.app = app; + } + + public static List<CacheListApp> getActiveApps() { + final List<CacheListApp> activeApps = new ArrayList<>(); + for (final CacheListApps appEnum : values()) { + if (appEnum.app.isInstalled()) { + activeApps.add(appEnum.app); + } + } + return activeApps; + } + +} + diff --git a/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java b/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java index 9216bc0..d364cda 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java +++ b/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java @@ -22,7 +22,7 @@ class InternalCacheListMap extends AbstractApp implements CacheListApp { } @Override - public boolean invoke(List<Geocache> caches, Activity activity, final SearchResult search) { + public boolean invoke(final List<Geocache> caches, final Activity activity, final SearchResult search) { CGeoMap.startActivitySearch(activity, search, null); return true; } diff --git a/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java new file mode 100644 index 0000000..6a49995 --- /dev/null +++ b/main/src/cgeo/geocaching/apps/cachelist/ListNavigationSelectionActionProvider.java @@ -0,0 +1,60 @@ +package cgeo.geocaching.apps.cachelist; + +import cgeo.geocaching.ui.AbstractMenuActionProvider; + +import android.content.Context; +import android.support.v4.view.ActionProvider; +import android.support.v4.view.MenuItemCompat; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.SubMenu; + +import java.util.List; + +public class ListNavigationSelectionActionProvider extends AbstractMenuActionProvider { + + public static interface Callback { + void onListNavigationSelected(final CacheListApp app); + } + + private Callback callback; + + public ListNavigationSelectionActionProvider(final Context context) { + super(context); + } + + public void setCallback(final Callback callback) { + this.callback = callback; + } + + @Override + public void onPrepareSubMenu(final SubMenu subMenu) { + subMenu.clear(); + if (callback == null) { + return; + } + final List<CacheListApp> activeApps = CacheListApps.getActiveApps(); + for (int i = 0; i < activeApps.size(); i++) { + final CacheListApp app = activeApps.get(i); + subMenu.add(Menu.NONE, i, Menu.NONE, app.getName()).setOnMenuItemClickListener(new OnMenuItemClickListener() { + + @Override + public boolean onMenuItemClick(final MenuItem item) { + final CacheListApp app = activeApps.get(item.getItemId()); + callback.onListNavigationSelected(app); + return true; + } + }); + } + } + + public static void initialize(final MenuItem menuItem, final Callback callback) { + final ActionProvider actionProvider = MenuItemCompat.getActionProvider(menuItem); + if (actionProvider instanceof ListNavigationSelectionActionProvider) { + final ListNavigationSelectionActionProvider navigateAction = (ListNavigationSelectionActionProvider) actionProvider; + navigateAction.setCallback(callback); + } + } + +} diff --git a/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java index ba177f0..ed64d2d 100644 --- a/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java +++ b/main/src/cgeo/geocaching/apps/cachelist/MapsWithMeCacheListApp.java @@ -26,10 +26,10 @@ public class MapsWithMeCacheListApp extends AbstractApp implements CacheListApp } @Override - public boolean invoke(List<Geocache> caches, Activity activity, SearchResult search) { + public boolean invoke(final List<Geocache> caches, final Activity activity, final SearchResult search) { final MWMPoint[] points = new MWMPoint[caches.size()]; for (int i = 0; i < points.length; i++) { - Geocache geocache = caches.get(i); + final Geocache geocache = caches.get(i); points[i] = new MWMPoint(geocache.getCoords().getLatitude(), geocache.getCoords().getLongitude(), geocache.getName(), geocache.getGeocode()); } MapsWithMeApi.showPointsOnMap(activity, null, getPendingIntent(activity), points); @@ -44,22 +44,19 @@ public class MapsWithMeCacheListApp extends AbstractApp implements CacheListApp /** * get cache code from a PendingIntent after an invocation of MapsWithMe - * - * @return + * */ @Nullable public static String getCacheFromMapsWithMe(final Context context, final Intent intent) { final MWMResponse mwmResponse = MWMResponse.extractFromIntent(context, intent); - if (mwmResponse != null) { - final MWMPoint point = mwmResponse.getPoint(); - if (point != null) { - return point.getId(); - } + final MWMPoint point = mwmResponse.getPoint(); + if (point != null) { + return point.getId(); } return null; } - private static PendingIntent getPendingIntent(Context context) { + private static PendingIntent getPendingIntent(final Context context) { final Intent intent = new Intent(context, CacheDetailActivity.class); return PendingIntent.getActivity(context, 0, intent, 0); } diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java new file mode 100644 index 0000000..8398eb3 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java @@ -0,0 +1,15 @@ +package cgeo.geocaching.compatibility; + +import android.annotation.TargetApi; +import android.os.Build; +import android.widget.TextView; + +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class AndroidLevel11 implements AndroidLevel11Interface { + + @Override + public void setTextIsSelectable(final TextView textView, final boolean selectable) { + textView.setTextIsSelectable(selectable); + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java new file mode 100644 index 0000000..b4111ab --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java @@ -0,0 +1,12 @@ +package cgeo.geocaching.compatibility; + +import android.widget.TextView; + +public class AndroidLevel11Emulation implements AndroidLevel11Interface { + + @Override + public void setTextIsSelectable(final TextView textView, final boolean selectable) { + // do nothing + } + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java new file mode 100644 index 0000000..45c06a4 --- /dev/null +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java @@ -0,0 +1,9 @@ +package cgeo.geocaching.compatibility; + +import android.widget.TextView; + +public interface AndroidLevel11Interface { + + void setTextIsSelectable(TextView textView, boolean selectable); + +} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java index eb2be4b..f599611 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java @@ -8,16 +8,11 @@ import android.graphics.Point; import android.view.WindowManager; @TargetApi(value = 13) -public class AndroidLevel13 implements AndroidLevel13Interface { - - @Override - public int getDisplayWidth() { - return getDisplaySize().x; - } +class AndroidLevel13 implements AndroidLevel13Interface { @Override public Point getDisplaySize() { - Point dimensions = new Point(); + final Point dimensions = new Point(); ((WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay().getSize(dimensions); return dimensions; diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java index 56c784f..f9fd3bc 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java @@ -8,12 +8,7 @@ import android.view.Display; import android.view.WindowManager; @SuppressWarnings("deprecation") -public class AndroidLevel13Emulation implements AndroidLevel13Interface { - - @Override - public int getDisplayWidth() { - return getDisplay().getWidth(); - } +class AndroidLevel13Emulation implements AndroidLevel13Interface { @Override public Point getDisplaySize() { diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java index 8483e38..b78875f 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java @@ -2,8 +2,7 @@ package cgeo.geocaching.compatibility; import android.graphics.Point; -public interface AndroidLevel13Interface { - int getDisplayWidth(); +interface AndroidLevel13Interface { Point getDisplaySize(); } diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel19.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel19.java index ed4849f..6b15a00 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel19.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel19.java @@ -5,12 +5,12 @@ import android.app.Activity; import android.content.Intent; @TargetApi(19) -public class AndroidLevel19 implements AndroidLevel19Interface { +class AndroidLevel19 implements AndroidLevel19Interface { @Override public void importGpxFromStorageAccessFramework(final Activity activity, final int requestCode) { // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file browser. - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); // Filter to only show results that can be "opened", such as a file (as opposed to a list // of contacts or timezones) diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel19Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel19Emulation.java index 99f140f..7404c82 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel19Emulation.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel19Emulation.java @@ -2,10 +2,10 @@ package cgeo.geocaching.compatibility; import android.app.Activity; -public class AndroidLevel19Emulation implements AndroidLevel19Interface { +class AndroidLevel19Emulation implements AndroidLevel19Interface { @Override - public void importGpxFromStorageAccessFramework(Activity activity, int requestCode) { + public void importGpxFromStorageAccessFramework(final Activity activity, final int requestCode) { // do nothing } diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel19Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel19Interface.java index 9a27cd8..de397a6 100644 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel19Interface.java +++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel19Interface.java @@ -2,6 +2,6 @@ package cgeo.geocaching.compatibility; import android.app.Activity; -public interface AndroidLevel19Interface { +interface AndroidLevel19Interface { void importGpxFromStorageAccessFramework(Activity activity, final int requestCode); } diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index 54e2966..56e18bf 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -5,15 +5,18 @@ import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.graphics.Point; import android.os.Build; +import android.widget.TextView; public final class Compatibility { private static final int SDK_VERSION = Build.VERSION.SDK_INT; + private static final AndroidLevel11Interface LEVEL_11; private static final AndroidLevel13Interface LEVEL_13; private static final AndroidLevel19Interface LEVEL_19; static { + LEVEL_11 = SDK_VERSION >= 11 ? new AndroidLevel11() : new AndroidLevel11Emulation(); LEVEL_13 = SDK_VERSION >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation(); LEVEL_19 = SDK_VERSION >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation(); } @@ -22,19 +25,19 @@ public final class Compatibility { // utility class } - public static int getDisplayWidth() { - return LEVEL_13.getDisplayWidth(); - } - public static Point getDisplaySize() { return LEVEL_13.getDisplaySize(); } - public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, int requestCodeImportGpx) { + public static void importGpxFromStorageAccessFramework(final @NonNull Activity activity, final int requestCodeImportGpx) { LEVEL_19.importGpxFromStorageAccessFramework(activity, requestCodeImportGpx); } public static boolean isStorageAccessFrameworkAvailable() { return SDK_VERSION >= 19; } + + public static void setTextIsSelectable(final TextView textView, final boolean selectable) { + LEVEL_11.setTextIsSelectable(textView, selectable); + } } diff --git a/main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java b/main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java deleted file mode 100644 index a6d7e9b..0000000 --- a/main/src/cgeo/geocaching/concurrent/BlockingThreadPool.java +++ /dev/null @@ -1,57 +0,0 @@ -package cgeo.geocaching.concurrent; - - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * BlockingThreadPool restricts the amount of parallel threads executing Runnables. - */ -public class BlockingThreadPool { - /** The queue holding the Runnable. **/ - private BlockingQueue<Runnable> queue = null; - /** The Executor. **/ - private ThreadPoolExecutor executor; - - /** - * Creates a ThreadPool with a given maximum of parallel threads running. - * Idle threads will be stopped until new threads are added. - * - * @param poolSize - * Maximum amout of parallel Threads - * @param priority - * The Thread priority e.g. Thread.MIN_PRIORITY - */ - public BlockingThreadPool(int poolSize, int priority) { - ThreadFactory threadFactory = new PriorityThreadFactory(priority); - this.queue = new ArrayBlockingQueue<>(poolSize, true); - this.executor = new ThreadPoolExecutor(0, poolSize, 5, TimeUnit.SECONDS, this.queue); - this.executor.setThreadFactory(threadFactory); - } - - /** - * Add a runnable to the pool. This will start the core threads in the underlying - * executor and try to add the Runnable to the pool. This method waits until timeout - * if no free thread is available. - * - * @param task - * The Runnable to add to the pool - * @param timeout - * The timeout to wait for a free thread - * @param unit - * The timeout unit - * @return true/false successful added - * @throws InterruptedException - * Operation was interrupted - */ - public boolean add(Runnable task, int timeout, TimeUnit unit) throws InterruptedException { - this.executor.setCorePoolSize(this.executor.getMaximumPoolSize()); - this.executor.prestartAllCoreThreads(); - boolean successfull = this.queue.offer(task, timeout, unit); - this.executor.setCorePoolSize(0); - return successfull; - } -} diff --git a/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java b/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java deleted file mode 100644 index 0da198b..0000000 --- a/main/src/cgeo/geocaching/concurrent/PriorityThreadFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package cgeo.geocaching.concurrent; - -import org.eclipse.jdt.annotation.NonNull; - -import java.util.concurrent.ThreadFactory; - -/** - * Helper class for setting Thread priority in ThreadPool. - */ -public class PriorityThreadFactory implements ThreadFactory { - private int priority; - - public PriorityThreadFactory(int priority) { - this.priority = priority; - } - - @NonNull - @Override - public Thread newThread(Runnable r) { - Thread result = new Thread(r); - result.setPriority(this.priority); - return result; - } - -} diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 9729e06..0583aa1 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -15,10 +15,12 @@ import cgeo.geocaching.connector.capability.ISearchByOwner; import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import rx.functions.Action1; import java.util.ArrayList; @@ -38,12 +40,12 @@ public abstract class AbstractConnector implements IConnector { } @Override - public boolean addToWatchlist(Geocache cache) { + public boolean addToWatchlist(@NonNull final Geocache cache) { return false; } @Override - public boolean removeFromWatchlist(Geocache cache) { + public boolean removeFromWatchlist(@NonNull final Geocache cache) { return false; } @@ -53,7 +55,7 @@ public abstract class AbstractConnector implements IConnector { } @Override - public boolean uploadPersonalNote(Geocache cache) { + public boolean uploadPersonalNote(@NonNull final Geocache cache) { throw new UnsupportedOperationException(); } @@ -63,7 +65,7 @@ public abstract class AbstractConnector implements IConnector { } @Override - public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) { + public boolean uploadModifiedCoordinates(@NonNull final Geocache cache, @NonNull final Geopoint wpt) { throw new UnsupportedOperationException(); } @@ -71,12 +73,12 @@ public abstract class AbstractConnector implements IConnector { * {@link IConnector} */ @Override - public boolean deleteModifiedCoordinates(Geocache cache) { + public boolean deleteModifiedCoordinates(@NonNull final Geocache cache) { throw new UnsupportedOperationException(); } @Override - public boolean supportsFavoritePoints(final Geocache cache) { + public boolean supportsFavoritePoints(@NonNull final Geocache cache) { return false; } @@ -91,46 +93,48 @@ public abstract class AbstractConnector implements IConnector { } @Override - public boolean canLog(Geocache cache) { + public boolean canLog(@NonNull final Geocache cache) { return false; } @Override - public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) { + @NonNull + public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) { return new NoLoggingManager(); } @Override + @NonNull public String getLicenseText(final @NonNull Geocache cache) { - return null; + return StringUtils.EMPTY; } - protected static boolean isNumericId(final String string) { + protected static boolean isNumericId(final String str) { try { - return Integer.parseInt(string) > 0; - } catch (NumberFormatException e) { + return Integer.parseInt(str) > 0; + } catch (final NumberFormatException ignored) { } return false; } @Override - public boolean isZippedGPXFile(String fileName) { + public boolean isZippedGPXFile(@NonNull final String fileName) { // don't accept any file by default return false; } @Override - public boolean isReliableLatLon(boolean cacheHasReliableLatLon) { + public boolean isReliableLatLon(final boolean cacheHasReliableLatLon) { // let every cache have reliable coordinates by default return true; } @Override - public String getGeocodeFromUrl(final String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { final String urlPrefix = getCacheUrlPrefix(); - if (StringUtils.startsWith(url, urlPrefix)) { - @NonNull - String geocode = url.substring(urlPrefix.length()); + if (StringUtils.isEmpty(urlPrefix) || StringUtils.startsWith(url, urlPrefix)) { + @NonNull final String geocode = url.substring(urlPrefix.length()); if (canHandle(geocode)) { return geocode; } @@ -138,9 +142,11 @@ public abstract class AbstractConnector implements IConnector { return null; } + @NonNull abstract protected String getCacheUrlPrefix(); @Override + @Nullable public String getLongCacheUrl(final @NonNull Geocache cache) { return getCacheUrl(cache); } @@ -151,7 +157,7 @@ public abstract class AbstractConnector implements IConnector { } @Override - public int getCacheMapMarkerId(boolean disabled) { + public int getCacheMapMarkerId(final boolean disabled) { if (disabled) { return R.drawable.marker_disabled_other; } @@ -159,7 +165,8 @@ public abstract class AbstractConnector implements IConnector { } @Override - public List<LogType> getPossibleLogTypes(Geocache geocache) { + @NonNull + public List<LogType> getPossibleLogTypes(@NonNull final Geocache geocache) { final List<LogType> logTypes = new ArrayList<>(); if (geocache.isEventCache()) { logTypes.add(LogType.WILL_ATTEND); @@ -196,13 +203,14 @@ public abstract class AbstractConnector implements IConnector { } @Override - public String getWaypointGpxId(String prefix, String geocode) { + public String getWaypointGpxId(final String prefix, @NonNull final String geocode) { // Default: just return the prefix return prefix; } @Override - public String getWaypointPrefix(String name) { + @NonNull + public String getWaypointPrefix(final String name) { // Default: just return the name return name; } @@ -213,8 +221,9 @@ public abstract class AbstractConnector implements IConnector { } @Override + @NonNull public final Collection<String> getCapabilities() { - ArrayList<String> list = new ArrayList<>(); + final ArrayList<String> list = new ArrayList<>(); addCapability(list, ISearchByViewPort.class, R.string.feature_search_live_map); addCapability(list, ISearchByKeyword.class, R.string.feature_search_keyword); addCapability(list, ISearchByCenter.class, R.string.feature_search_center); @@ -245,20 +254,20 @@ public abstract class AbstractConnector implements IConnector { } } - private static String feature(int featureResourceId) { + private static String feature(final int featureResourceId) { return CgeoApplication.getInstance().getString(featureResourceId); } @Override public @NonNull List<UserAction> getUserActions() { - List<UserAction> actions = getDefaultUserActions(); + final List<UserAction> actions = getDefaultUserActions(); if (this instanceof ISearchByOwner) { actions.add(new UserAction(R.string.user_menu_view_hidden, new Action1<Context>() { @Override - public void call(Context context) { + public void call(final Context context) { CacheListActivity.startActivityOwner(context.activity, context.userName); } })); @@ -268,7 +277,7 @@ public abstract class AbstractConnector implements IConnector { actions.add(new UserAction(R.string.user_menu_view_found, new Action1<UserAction.Context>() { @Override - public void call(Context context) { + public void call(final Context context) { CacheListActivity.startActivityFinder(context.activity, context.userName); } })); @@ -286,7 +295,7 @@ public abstract class AbstractConnector implements IConnector { actions.add(new UserAction(R.string.user_menu_open_contact, new Action1<UserAction.Context>() { @Override - public void call(Context context) { + public void call(final Context context) { ContactsAddon.openContactCard(context.activity, context.userName); } })); @@ -295,4 +304,6 @@ public abstract class AbstractConnector implements IConnector { return actions; } + public void logout() { + } } diff --git a/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java b/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java index 9e702c4..e53fcf1 100644 --- a/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/AbstractLoggingManager.java @@ -2,6 +2,8 @@ package cgeo.geocaching.connector; import cgeo.geocaching.TrackableLog; +import org.eclipse.jdt.annotation.NonNull; + import java.util.Collections; import java.util.List; @@ -13,6 +15,7 @@ public abstract class AbstractLoggingManager implements ILoggingManager { } @Override + @NonNull public List<TrackableLog> getTrackables() { return Collections.emptyList(); } diff --git a/main/src/cgeo/geocaching/connector/AbstractLogin.java b/main/src/cgeo/geocaching/connector/AbstractLogin.java index 6527685..252daeb 100644 --- a/main/src/cgeo/geocaching/connector/AbstractLogin.java +++ b/main/src/cgeo/geocaching/connector/AbstractLogin.java @@ -4,9 +4,11 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Cookies; +import cgeo.geocaching.network.Network; import cgeo.geocaching.settings.Settings; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; public abstract class AbstractLogin { @@ -38,7 +40,7 @@ public abstract class AbstractLogin { return actualLoginStatus; } - protected void setActualLoginStatus(boolean loginStatus) { + protected void setActualLoginStatus(final boolean loginStatus) { actualLoginStatus = loginStatus; } @@ -46,7 +48,7 @@ public abstract class AbstractLogin { return actualUserName; } - protected void setActualUserName(String userName) { + protected void setActualUserName(final String userName) { actualUserName = userName; } @@ -68,10 +70,15 @@ public abstract class AbstractLogin { setActualStatus(CgeoApplication.getInstance().getString(R.string.err_login)); } + @NonNull public StatusCode login() { + if (!Network.isNetworkConnected()) { + return StatusCode.COMMUNICATION_ERROR; + } return login(true); } + @NonNull protected abstract StatusCode login(boolean retry); } diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index e6ef829..918911a 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -1,6 +1,6 @@ package cgeo.geocaching.connector; -import cgeo.geocaching.ICache; +import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Trackable; @@ -15,13 +15,15 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.MapTokens; import cgeo.geocaching.connector.oc.OCApiConnector.ApiSupport; import cgeo.geocaching.connector.oc.OCApiLiveConnector; +import cgeo.geocaching.connector.oc.OCCZConnector; import cgeo.geocaching.connector.oc.OCConnector; import cgeo.geocaching.connector.ox.OXConnector; import cgeo.geocaching.connector.trackable.GeokretyConnector; +import cgeo.geocaching.connector.trackable.SwaggieConnector; import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.connector.trackable.TravelBugConnector; import cgeo.geocaching.connector.trackable.UnknownTrackableConnector; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Viewport; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; @@ -36,14 +38,14 @@ import java.util.Collections; import java.util.List; public final class ConnectorFactory { - private static final @NonNull UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector(); - private static final Collection<IConnector> CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new IConnector[] { + @NonNull private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector(); + @NonNull private static final Collection<IConnector> CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new IConnector[] { GCConnector.getInstance(), ECConnector.getInstance(), new OCApiLiveConnector("opencaching.de", "www.opencaching.de", "OC", "CC BY-NC-ND, alle Logeinträge © jeweiliger Autor", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, R.string.pref_connectorOCActive, R.string.pref_ocde_tokenpublic, R.string.pref_ocde_tokensecret, ApiSupport.current), - new OCConnector("OpenCaching.CZ", "www.opencaching.cz", "OZ"), + new OCCZConnector(), new OCApiLiveConnector("opencaching.org.uk", "www.opencaching.org.uk", "OK", "CC BY-NC-SA 2.5", R.string.oc_uk_okapi_consumer_key, R.string.oc_uk_okapi_consumer_secret, R.string.pref_connectorOCUKActive, R.string.pref_ocuk_tokenpublic, R.string.pref_ocuk_tokensecret, ApiSupport.oldapi), @@ -71,22 +73,31 @@ public final class ConnectorFactory { })); @NonNull public static final UnknownTrackableConnector UNKNOWN_TRACKABLE_CONNECTOR = new UnknownTrackableConnector(); + + @NonNull private static final Collection<TrackableConnector> TRACKABLE_CONNECTORS = Collections.unmodifiableCollection(Arrays.asList(new TrackableConnector[] { - new GeokretyConnector(), // GK must be first, as it overlaps with the secret codes of travel bugs - TravelBugConnector.getInstance(), + new GeokretyConnector(), + new SwaggieConnector(), + TravelBugConnector.getInstance(), // travel bugs last, as their secret codes overlap with other connectors UNKNOWN_TRACKABLE_CONNECTOR // must be last })); + @NonNull private static final Collection<ISearchByViewPort> searchByViewPortConns = getMatchingConnectors(ISearchByViewPort.class); + @NonNull private static final Collection<ISearchByCenter> searchByCenterConns = getMatchingConnectors(ISearchByCenter.class); + @NonNull private static final Collection<ISearchByKeyword> searchByKeywordConns = getMatchingConnectors(ISearchByKeyword.class); + @NonNull private static final Collection<ISearchByOwner> SEARCH_BY_OWNER_CONNECTORS = getMatchingConnectors(ISearchByOwner.class); + @NonNull private static final Collection<ISearchByFinder> SEARCH_BY_FINDER_CONNECTORS = getMatchingConnectors(ISearchByFinder.class); + @NonNull @SuppressWarnings("unchecked") private static <T extends IConnector> Collection<T> getMatchingConnectors(final Class<T> clazz) { final List<T> matching = new ArrayList<>(); @@ -98,26 +109,32 @@ public final class ConnectorFactory { return Collections.unmodifiableCollection(matching); } + @NonNull public static Collection<IConnector> getConnectors() { return CONNECTORS; } + @NonNull public static Collection<ISearchByCenter> getSearchByCenterConnectors() { return searchByCenterConns; } + @NonNull public static Collection<ISearchByKeyword> getSearchByKeywordConnectors() { return searchByKeywordConns; } + @NonNull public static Collection<ISearchByOwner> getSearchByOwnerConnectors() { return SEARCH_BY_OWNER_CONNECTORS; } + @NonNull public static Collection<ISearchByFinder> getSearchByFinderConnectors() { return SEARCH_BY_FINDER_CONNECTORS; } + @NonNull public static ILogin[] getActiveLiveConnectors() { final List<ILogin> liveConns = new ArrayList<>(); for (final IConnector conn : CONNECTORS) { @@ -143,11 +160,12 @@ public final class ConnectorFactory { return false; } - public static @NonNull - IConnector getConnector(final ICache cache) { + @NonNull + public static IConnector getConnector(final Geocache cache) { return getConnector(cache.getGeocode()); } + @NonNull public static TrackableConnector getConnector(final Trackable trackable) { return getTrackableConnector(trackable.getGeocode()); } @@ -162,8 +180,8 @@ public final class ConnectorFactory { return UNKNOWN_TRACKABLE_CONNECTOR; // avoid null checks by returning a non implementing connector } - public static @NonNull - IConnector getConnector(final String geocodeInput) { + @NonNull + public static IConnector getConnector(final String geocodeInput) { // this may come from user input final String geocode = StringUtils.trim(geocodeInput); if (geocode == null) { @@ -186,7 +204,8 @@ public final class ConnectorFactory { } /** @see ISearchByViewPort#searchByViewport */ - public static SearchResult searchByViewport(final @NonNull Viewport viewport, final MapTokens tokens) { + @NonNull + public static SearchResult searchByViewport(final @NonNull Viewport viewport, @NonNull final MapTokens tokens) { return SearchResult.parallelCombineActive(searchByViewPortConns, new Func1<ISearchByViewPort, SearchResult>() { @Override public SearchResult call(final ISearchByViewPort connector) { @@ -195,9 +214,13 @@ public final class ConnectorFactory { }); } - public static String getGeocodeFromURL(final String url) { + @Nullable + public static String getGeocodeFromURL(@Nullable final String url) { + if (url == null) { + return null; + } for (final IConnector connector : CONNECTORS) { - final String geocode = connector.getGeocodeFromUrl(url); + @Nullable final String geocode = connector.getGeocodeFromUrl(url); if (StringUtils.isNotBlank(geocode)) { return geocode; } @@ -205,6 +228,7 @@ public final class ConnectorFactory { return null; } + @NonNull public static Collection<TrackableConnector> getTrackableConnectors() { return TRACKABLE_CONNECTORS; } @@ -212,9 +236,9 @@ public final class ConnectorFactory { /** * Get the geocode of a trackable from a URL. * - * @param url * @return {@code null} if the URL cannot be decoded */ + @Nullable public static String getTrackableFromURL(final String url) { if (url == null) { return null; diff --git a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java index 3992013..9377d6d 100644 --- a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java +++ b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java @@ -1,30 +1,32 @@ package cgeo.geocaching.connector; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; -public class GeocachingAustraliaConnector extends AbstractConnector { +class GeocachingAustraliaConnector extends AbstractConnector { @Override + @NonNull public String getName() { return "Geocaching Australia"; } @Override + @NonNull public String getCacheUrl(final @NonNull Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } @Override + @NonNull public String getHost() { return "geocaching.com.au"; } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return false; } @@ -34,6 +36,7 @@ public class GeocachingAustraliaConnector extends AbstractConnector { } @Override + @NonNull protected String getCacheUrlPrefix() { return "http://" + getHost() + "/cache/"; } diff --git a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java index aa08485..4340cac 100644 --- a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java +++ b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java @@ -1,39 +1,42 @@ package cgeo.geocaching.connector; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; -public class GeopeitusConnector extends AbstractConnector { +class GeopeitusConnector extends AbstractConnector { @Override + @NonNull public String getName() { return "geopeitus.ee"; } @Override + @NonNull public String getCacheUrl(final @NonNull Geocache cache) { return getCacheUrlPrefix() + StringUtils.stripStart(cache.getGeocode().substring(2), "0"); } @Override + @NonNull public String getHost() { return "www.geopeitus.ee"; } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return false; } @Override - public boolean canHandle(@NonNull String geocode) { + public boolean canHandle(@NonNull final String geocode) { return StringUtils.startsWith(geocode, "GE") && isNumericId(geocode.substring(2)); } @Override + @NonNull protected String getCacheUrlPrefix() { return "http://" + getHost() + "/aare/"; } diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index e6b6674..74b1028 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -1,12 +1,12 @@ package cgeo.geocaching.connector; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -15,8 +15,8 @@ public interface IConnector { /** * get name for display (currently only used in links) * - * @return */ + @NonNull public String getName(); /** @@ -31,109 +31,96 @@ public interface IConnector { /** * Get the browser URL for the given cache. * - * @param cache - * @return */ + @Nullable public String getCacheUrl(final @NonNull Geocache cache); /** * get long browser URL for the given cache * - * @param cache - * @return */ + @Nullable public String getLongCacheUrl(final @NonNull Geocache cache); /** * enable/disable watchlist controls in cache details * - * @return */ public boolean supportsWatchList(); /** * Add the cache to the watchlist * - * @param cache * @return True - success/False - failure */ - public boolean addToWatchlist(Geocache cache); + public boolean addToWatchlist(@NonNull Geocache cache); /** * Remove the cache from the watchlist * - * @param cache * @return True - success/False - failure */ - public boolean removeFromWatchlist(Geocache cache); + public boolean removeFromWatchlist(@NonNull Geocache cache); /** * enable/disable favorite points controls in cache details * - * @return */ - public boolean supportsFavoritePoints(final Geocache cache); + public boolean supportsFavoritePoints(@NonNull final Geocache cache); /** * enable/disable logging controls in cache details * - * @return */ public boolean supportsLogging(); /** * enable/disable attaching image to log * - * @return */ public boolean supportsLogImages(); /** * Get an ILoggingManager to guide the logging process. * - * @return */ - public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache); + @NonNull + public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache); /** * Get host name of the connector server for dynamic loading of data. * - * @return */ + @NonNull public String getHost(); /** * Get cache data license text. This is displayed somewhere near the cache details. * - * @param cache - * @return */ + @NonNull public String getLicenseText(final @NonNull Geocache cache); /** * return true if this is a ZIP file containing a GPX file * - * @param fileName - * @return */ - public boolean isZippedGPXFile(final String fileName); + public boolean isZippedGPXFile(@NonNull final String fileName); /** * return true if coordinates of a cache are reliable. only implemented by GC connector * * @param cacheHasReliableLatLon * flag of the cache - * @return */ public boolean isReliableLatLon(boolean cacheHasReliableLatLon); /** * extract a geocode from the given URL, if this connector can handle that URL somehow * - * @param url - * @return */ - public String getGeocodeFromUrl(final String url); + @Nullable + public String getGeocodeFromUrl(@NonNull final String url); /** * enable/disable uploading personal note @@ -145,10 +132,9 @@ public interface IConnector { /** * Uploading personal note to website * - * @param cache * @return success */ - public boolean uploadPersonalNote(Geocache cache); + public boolean uploadPersonalNote(@NonNull Geocache cache); /** * enable/disable uploading modified coordinates to website @@ -160,25 +146,21 @@ public interface IConnector { /** * Resetting of modified coordinates on website to details * - * @param cache * @return success */ - public boolean deleteModifiedCoordinates(Geocache cache); + public boolean deleteModifiedCoordinates(@NonNull Geocache cache); /** * Uploading modified coordinates to website * - * @param cache - * @param wpt * @return success */ - public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt); + public boolean uploadModifiedCoordinates(@NonNull Geocache cache, @NonNull Geopoint wpt); /** * Return {@code true} if this connector is active for online interaction (download details, do searches, ...). If * this is {@code false}, the connector will still be used for already stored offline caches. * - * @return */ public boolean isActive(); @@ -189,16 +171,14 @@ public interface IConnector { * @param cache a cache that this connector must be able to handle * @return <code>true</code> if the current user is the cache owner, <code>false</code> otherwise */ - public boolean isOwner(final ICache cache); + public boolean isOwner(@NonNull final Geocache cache); /** * Check if the cache information is complete enough to be * able to log online. * - * @param geocache - * @return */ - public boolean canLog(Geocache geocache); + public boolean canLog(@NonNull Geocache geocache); /** * Return the marker id of the caches for this connector. This creates the different backgrounds for cache markers @@ -213,42 +193,37 @@ public interface IConnector { * Get the list of <b>potentially</b> possible log types for a cache. Those may still be filtered further during the * actual logging activity. * - * @param geocache - * @return */ - public List<LogType> getPossibleLogTypes(Geocache geocache); + @NonNull + public List<LogType> getPossibleLogTypes(@NonNull Geocache geocache); /** * Get the GPX id for a waypoint when exporting. For some connectors there is an inherent name logic, * for others its just the 'prefix'. * - * @param prefix - * @return */ - public String getWaypointGpxId(String prefix, String geocode); + public String getWaypointGpxId(String prefix, @NonNull String geocode); /** * Get the 'prefix' (key) for a waypoint from the 'name' in the GPX file * - * @param name - * @return */ + @NonNull public String getWaypointPrefix(String name); /** * Get the maximum value for Terrain * - * @return */ public int getMaxTerrain(); /** * Get a user readable collection of all online features of this connector. * - * @return */ + @NonNull public Collection<String> getCapabilities(); - public @NonNull - List<UserAction> getUserActions(); + @NonNull + public List<UserAction> getUserActions(); } diff --git a/main/src/cgeo/geocaching/connector/ILoggingManager.java b/main/src/cgeo/geocaching/connector/ILoggingManager.java index c5586b3..2b0a067 100644 --- a/main/src/cgeo/geocaching/connector/ILoggingManager.java +++ b/main/src/cgeo/geocaching/connector/ILoggingManager.java @@ -1,9 +1,11 @@ package cgeo.geocaching.connector; -import cgeo.geocaching.Geocache; import cgeo.geocaching.TrackableLog; import cgeo.geocaching.enumerations.LogType; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import android.net.Uri; import java.util.Calendar; @@ -13,23 +15,18 @@ public interface ILoggingManager { /** * Post a log for a cache online - * - * @param cache - * @param logType - * @param date - * @param log + * * @param logPassword * optional, maybe null - * @param trackableLogs - * @return */ - LogResult postLog(Geocache cache, - LogType logType, - Calendar date, - String log, - String logPassword, - List<TrackableLog> trackableLogs); - + @NonNull + LogResult postLog(@NonNull LogType logType, + @NonNull Calendar date, + @NonNull String log, + @Nullable String logPassword, + @NonNull List<TrackableLog> trackableLogs); + + @NonNull ImageResult postLogImage(String logId, String imageCaption, String imageDescription, @@ -37,8 +34,10 @@ public interface ILoggingManager { public boolean hasLoaderError(); + @NonNull public List<TrackableLog> getTrackables(); + @NonNull public List<LogType> getPossibleLogTypes(); public void init(); diff --git a/main/src/cgeo/geocaching/connector/ImageResult.java b/main/src/cgeo/geocaching/connector/ImageResult.java index 9314cad..ec11a6d 100644 --- a/main/src/cgeo/geocaching/connector/ImageResult.java +++ b/main/src/cgeo/geocaching/connector/ImageResult.java @@ -2,20 +2,26 @@ package cgeo.geocaching.connector; import cgeo.geocaching.enumerations.StatusCode; +import org.eclipse.jdt.annotation.NonNull; + public class ImageResult { + @NonNull private final StatusCode postResult; + @NonNull private final String imageUri; - public ImageResult(StatusCode postResult, String imageUri) { + public ImageResult(@NonNull final StatusCode postResult, @NonNull final String imageUri) { this.postResult = postResult; this.imageUri = imageUri; } + @NonNull public StatusCode getPostResult() { return postResult; } + @NonNull public String getImageUri() { return imageUri; } diff --git a/main/src/cgeo/geocaching/connector/LogResult.java b/main/src/cgeo/geocaching/connector/LogResult.java index 62111a4..9d0cb61 100644 --- a/main/src/cgeo/geocaching/connector/LogResult.java +++ b/main/src/cgeo/geocaching/connector/LogResult.java @@ -2,20 +2,26 @@ package cgeo.geocaching.connector; import cgeo.geocaching.enumerations.StatusCode; +import org.eclipse.jdt.annotation.NonNull; + public class LogResult { + @NonNull private final StatusCode postLogResult; + @NonNull private final String logId; - public LogResult(StatusCode postLogResult, String logId) { + public LogResult(@NonNull final StatusCode postLogResult, @NonNull final String logId) { this.postLogResult = postLogResult; this.logId = logId; } + @NonNull public StatusCode getPostLogResult() { return postLogResult; } + @NonNull public String getLogId() { return logId; } diff --git a/main/src/cgeo/geocaching/connector/NoLoggingManager.java b/main/src/cgeo/geocaching/connector/NoLoggingManager.java index e2e5d4c..103db68 100644 --- a/main/src/cgeo/geocaching/connector/NoLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/NoLoggingManager.java @@ -1,17 +1,19 @@ package cgeo.geocaching.connector; -import cgeo.geocaching.Geocache; import cgeo.geocaching.TrackableLog; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import android.net.Uri; import java.util.Calendar; import java.util.Collections; import java.util.List; -public class NoLoggingManager extends AbstractLoggingManager { +class NoLoggingManager extends AbstractLoggingManager { @Override public void init() { @@ -19,12 +21,14 @@ public class NoLoggingManager extends AbstractLoggingManager { } @Override - public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) { + @NonNull + public LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) { return new LogResult(StatusCode.LOG_POST_ERROR, ""); } @Override - public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) { + @NonNull + public ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) { return new ImageResult(StatusCode.LOG_POST_ERROR, ""); } @@ -34,6 +38,7 @@ public class NoLoggingManager extends AbstractLoggingManager { } @Override + @NonNull public List<LogType> getPossibleLogTypes() { return Collections.emptyList(); } diff --git a/main/src/cgeo/geocaching/connector/UnknownConnector.java b/main/src/cgeo/geocaching/connector/UnknownConnector.java index 05593d7..cabf03e 100644 --- a/main/src/cgeo/geocaching/connector/UnknownConnector.java +++ b/main/src/cgeo/geocaching/connector/UnknownConnector.java @@ -1,30 +1,33 @@ package cgeo.geocaching.connector; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; -public class UnknownConnector extends AbstractConnector { +class UnknownConnector extends AbstractConnector { @Override + @NonNull public String getName() { return "Unknown caches"; } @Override - public String getCacheUrl(@NonNull Geocache cache) { - return null; // we have no url for these caches + @Nullable + public String getCacheUrl(@NonNull final Geocache cache) { + return null; } @Override + @NonNull public String getHost() { - return null; // we have no host for these caches + return StringUtils.EMPTY; // we have no host for these caches } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return false; } @@ -34,7 +37,14 @@ public class UnknownConnector extends AbstractConnector { } @Override + @NonNull protected String getCacheUrlPrefix() { + throw new IllegalStateException("getCacheUrl cannot be called on unknown caches"); + } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { return null; } diff --git a/main/src/cgeo/geocaching/connector/UserAction.java b/main/src/cgeo/geocaching/connector/UserAction.java index e9ee4a3..082e32c 100644 --- a/main/src/cgeo/geocaching/connector/UserAction.java +++ b/main/src/cgeo/geocaching/connector/UserAction.java @@ -1,6 +1,7 @@ package cgeo.geocaching.connector; import org.eclipse.jdt.annotation.NonNull; + import rx.functions.Action1; import android.app.Activity; @@ -8,25 +9,26 @@ import android.app.Activity; public class UserAction { public static class Context { + @NonNull public final String userName; + @NonNull public final Activity activity; - public Context(String userName, Activity activity) { + public Context(@NonNull final String userName, @NonNull final Activity activity) { this.userName = userName; this.activity = activity; } } public final int displayResourceId; - private final @NonNull - Action1<Context> runnable; + @NonNull private final Action1<Context> runnable; - public UserAction(int displayResourceId, final @NonNull Action1<Context> runnable) { + public UserAction(final int displayResourceId, final @NonNull Action1<Context> runnable) { this.displayResourceId = displayResourceId; this.runnable = runnable; } - public void run(Context context) { + public void run(@NonNull final Context context) { runnable.call(context); } } diff --git a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java index 282ee31..3361341 100644 --- a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java +++ b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java @@ -1,41 +1,61 @@ package cgeo.geocaching.connector; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; -public class WaymarkingConnector extends AbstractConnector { +class WaymarkingConnector extends AbstractConnector { @Override + @NonNull public String getName() { return "Waymarking"; } @Override - public String getCacheUrl(@NonNull Geocache cache) { + @NonNull + public String getCacheUrl(@NonNull final Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } @Override + @NonNull public String getHost() { return "www.waymarking.com"; } @Override - public boolean isOwner(ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { // this connector has no user management return false; } @Override + @NonNull protected String getCacheUrlPrefix() { return "http://" + getHost() + "/waymarks/"; } @Override - public boolean canHandle(@NonNull String geocode) { + public boolean canHandle(@NonNull final String geocode) { return StringUtils.startsWith(geocode, "WM"); } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + // coord.info URLs + String code = StringUtils.substringAfterLast(url, "coord.info/"); + if (code != null && canHandle(code)) { + return code; + } + // waymarking URLs http://www.waymarking.com/waymarks/WMNCDT_American_Legion_Flagpole_1983_University_of_Oregon + code = StringUtils.substringBetween(url, "waymarks/", "_"); + if (code != null && canHandle(code)) { + return code; + } + return null; + } } diff --git a/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java b/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java index 4da9705..dd2bc8d 100644 --- a/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java +++ b/main/src/cgeo/geocaching/connector/capability/FieldNotesCapability.java @@ -2,6 +2,8 @@ package cgeo.geocaching.connector.capability; import cgeo.geocaching.connector.IConnector; +import org.eclipse.jdt.annotation.NonNull; + import java.io.File; /** @@ -9,5 +11,5 @@ import java.io.File; * */ public interface FieldNotesCapability extends IConnector { - public boolean uploadFieldNotes(final File exportFile); + public boolean uploadFieldNotes(@NonNull final File exportFile); } diff --git a/main/src/cgeo/geocaching/connector/capability/ILogin.java b/main/src/cgeo/geocaching/connector/capability/ILogin.java index 4a839c8..437eec8 100644 --- a/main/src/cgeo/geocaching/connector/capability/ILogin.java +++ b/main/src/cgeo/geocaching/connector/capability/ILogin.java @@ -7,13 +7,10 @@ import android.os.Handler; public interface ILogin extends IConnector { - /** - * Contacts the server the connector belongs to - * and verifies/establishes authentication and - * retrieves information about the current user - * (Name, found caches) if applicable. - * + * Contacts the server the connector belongs to and verifies/establishes authentication and retrieves information + * about the current user (Name, found caches) if applicable. + * * @param handler * Handler to receive status feedback * @param fromActivity @@ -23,34 +20,34 @@ public interface ILogin extends IConnector { boolean login(Handler handler, Context fromActivity); /** - * Returns the status of the last {@link}login() request + * Log out of the connector if possible. + */ + void logout(); + + /** + * Returns the status of the last {@link #login(Handler, Context)} request. * - * @return */ boolean isLoggedIn(); /** * User-centered string describing the current login/connection status * - * @return */ String getLoginStatusString(); /** - * Name the user has in this connector or empty string if not applicable - * It might be necessary to execute login before this information is valid. + * Name the user has in this connector or empty string if not applicable. + * It might be necessary to execute {@link #login(Handler, Context)} before this information is valid. * - * @return */ String getUserName(); /** - * Number of caches the user has found in this connector - * Normally retrieved/updated with (@see login). - * Might be out dated as changes on the connectors site - * are generally not notified. + * Number of caches the user has found in this connector. + * Normally retrieved/updated with {@link #login(Handler, Context)}. + * Might be stale as changes on the connectors site are generally not notified. * - * @return */ int getCachesFound(); diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java index adc36c7..576220d 100644 --- a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java +++ b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java @@ -2,8 +2,8 @@ package cgeo.geocaching.connector.capability; import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.IConnector; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.Geopoint; import org.eclipse.jdt.annotation.NonNull; diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java index 7981ba8..0137c3b 100644 --- a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java +++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java @@ -3,10 +3,11 @@ package cgeo.geocaching.connector.capability; import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.connector.gc.MapTokens; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Viewport; import org.eclipse.jdt.annotation.NonNull; public interface ISearchByViewPort extends IConnector { - public SearchResult searchByViewport(final @NonNull Viewport viewport, final MapTokens tokens); + @NonNull + public SearchResult searchByViewport(final @NonNull Viewport viewport, @NonNull final MapTokens tokens); } diff --git a/main/src/cgeo/geocaching/connector/capability/IgnoreCapability.java b/main/src/cgeo/geocaching/connector/capability/IgnoreCapability.java new file mode 100644 index 0000000..5eca3f2 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/capability/IgnoreCapability.java @@ -0,0 +1,14 @@ +package cgeo.geocaching.connector.capability; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.connector.IConnector; + +import org.eclipse.jdt.annotation.NonNull; + +/** + * Connector capability to ignore caches. + */ +public interface IgnoreCapability extends IConnector { + public boolean canIgnoreCache(final @NonNull Geocache cache); + public void ignoreCache(final @NonNull Geocache cache); +} diff --git a/main/src/cgeo/geocaching/connector/ec/ECApi.java b/main/src/cgeo/geocaching/connector/ec/ECApi.java index 421d112..86f7717 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECApi.java +++ b/main/src/cgeo/geocaching/connector/ec/ECApi.java @@ -9,22 +9,25 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.files.GPX10Parser; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.SynchronizedDateFormat; import ch.boye.httpclientandroidlib.HttpResponse; +import com.fasterxml.jackson.databind.JsonNode; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -34,18 +37,27 @@ import java.util.List; import java.util.Locale; import java.util.TimeZone; -public class ECApi { +final class ECApi { + @NonNull private static final String API_HOST = "https://extremcaching.com/exports/"; + @NonNull private static final ECLogin ecLogin = ECLogin.getInstance(); + + @NonNull private static final SynchronizedDateFormat LOG_DATE_FORMAT = new SynchronizedDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US); - public static String getIdFromGeocode(final String geocode) { + private ECApi() { + // utility class with static methods + } + + static String getIdFromGeocode(final String geocode) { return StringUtils.removeStartIgnoreCase(geocode, "EC"); } - public static Geocache searchByGeoCode(final String geocode) { + @Nullable + static Geocache searchByGeoCode(final String geocode) { final Parameters params = new Parameters("id", getIdFromGeocode(geocode)); final HttpResponse response = apiRequest("gpx.php", params); @@ -56,7 +68,8 @@ public class ECApi { return null; } - public static Collection<Geocache> searchByBBox(final Viewport viewport) { + @NonNull + static Collection<Geocache> searchByBBox(final Viewport viewport) { if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) { return Collections.emptyList(); @@ -72,8 +85,8 @@ public class ECApi { return importCachesFromJSON(response); } - - public static Collection<Geocache> searchByCenter(final Geopoint center) { + @NonNull + static Collection<Geocache> searchByCenter(final Geopoint center) { final Parameters params = new Parameters("fnc", "center"); params.add("distance", "20"); @@ -84,11 +97,13 @@ public class ECApi { return importCachesFromJSON(response); } - public static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log) { + @NonNull + static LogResult postLog(@NonNull final Geocache cache, @NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log) { return postLog(cache, logType, date, log, false); } - public static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, boolean isRetry) { + @NonNull + private static LogResult postLog(@NonNull final Geocache cache, @NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, final boolean isRetry) { final Parameters params = new Parameters("cache_id", cache.getGeocode()); params.add("type", logType.type); params.add("log", log); @@ -99,7 +114,7 @@ public class ECApi { final HttpResponse response = Network.postRequest(uri, params); if (response == null) { - return new LogResult(StatusCode.LOG_POST_ERROR_EC, ""); + return new LogResult(StatusCode.LOG_POST_ERROR, ""); } if (!isRetry && response.getStatusLine().getStatusCode() == 403) { if (ecLogin.login() == StatusCode.NO_ERROR) { @@ -107,7 +122,7 @@ public class ECApi { } } if (response.getStatusLine().getStatusCode() != 200) { - return new LogResult(StatusCode.LOG_POST_ERROR_EC, ""); + return new LogResult(StatusCode.LOG_POST_ERROR, ""); } final String data = Network.getResponseDataAlways(response); @@ -119,18 +134,20 @@ public class ECApi { return new LogResult(StatusCode.NO_ERROR, uid); } - return new LogResult(StatusCode.LOG_POST_ERROR_EC, ""); + return new LogResult(StatusCode.LOG_POST_ERROR, ""); } - + @Nullable private static HttpResponse apiRequest(final Parameters params) { return apiRequest("api.php", params); } + @Nullable private static HttpResponse apiRequest(final String uri, final Parameters params) { return apiRequest(uri, params, false); } + @Nullable private static HttpResponse apiRequest(final String uri, final Parameters params, final boolean isRetry) { // add session and cgeo marker on every request if (!isRetry) { @@ -155,64 +172,66 @@ public class ECApi { return response; } + @NonNull private static Collection<Geocache> importCachesFromGPXResponse(final HttpResponse response) { if (response == null) { return Collections.emptyList(); } try { - return new GPX10Parser(StoredList.TEMPORARY_LIST_ID).parse(response.getEntity().getContent(), null); - } catch (Exception e) { + return new GPX10Parser(StoredList.TEMPORARY_LIST.id).parse(response.getEntity().getContent(), null); + } catch (final Exception e) { Log.e("Error importing gpx from extremcaching.com", e); return Collections.emptyList(); } } + @NonNull private static List<Geocache> importCachesFromJSON(final HttpResponse response) { if (response != null) { try { - final String data = Network.getResponseDataAlways(response); - if (StringUtils.isBlank(data) || StringUtils.equals(data, "[]")) { + final JsonNode json = JsonUtils.reader.readTree(Network.getResponseDataAlways(response)); + if (!json.isArray()) { return Collections.emptyList(); } - final JSONArray json = new JSONArray(data); - final int len = json.length(); - final List<Geocache> caches = new ArrayList<>(len); - for (int i = 0; i < len; i++) { - final Geocache cache = parseCache(json.getJSONObject(i)); + final List<Geocache> caches = new ArrayList<>(json.size()); + for (final JsonNode node: json) { + final Geocache cache = parseCache(node); if (cache != null) { caches.add(cache); } } return caches; - } catch (final JSONException e) { - Log.w("JSONResult", e); + } catch (IOException | ClassCastException e) { + Log.w("importCachesFromJSON", e); } } return Collections.emptyList(); } - private static Geocache parseCache(final JSONObject response) { - final Geocache cache = new Geocache(); - cache.setReliableLatLon(true); + @Nullable + private static Geocache parseCache(final JsonNode response) { try { - cache.setGeocode("EC" + response.getString("cache_id")); - cache.setName(response.getString("title")); - cache.setCoords(new Geopoint(response.getString("lat"), response.getString("lon"))); - cache.setType(getCacheType(response.getString("type"))); - cache.setDifficulty((float) response.getDouble("difficulty")); - cache.setTerrain((float) response.getDouble("terrain")); - cache.setSize(CacheSize.getById(response.getString("size"))); - cache.setFound(response.getInt("found") == 1); + final Geocache cache = new Geocache(); + cache.setReliableLatLon(true); + cache.setGeocode("EC" + response.get("cache_id").asText()); + cache.setName(response.get("title").asText()); + cache.setCoords(new Geopoint(response.get("lat").asText(), response.get("lon").asText())); + cache.setType(getCacheType(response.get("type").asText())); + cache.setDifficulty((float) response.get("difficulty").asDouble()); + cache.setTerrain((float) response.get("terrain").asDouble()); + cache.setSize(CacheSize.getById(response.get("size").asText())); + cache.setFound(response.get("found").asInt() == 1); DataStore.saveCache(cache, EnumSet.of(SaveFlag.CACHE)); - } catch (final JSONException e) { + return cache; + } catch (final NullPointerException e) { Log.e("ECApi.parseCache", e); return null; } - return cache; } + @NonNull private static CacheType getCacheType(final String cacheType) { if (cacheType.equalsIgnoreCase("Tradi")) { return CacheType.TRADITIONAL; diff --git a/main/src/cgeo/geocaching/connector/ec/ECConnector.java b/main/src/cgeo/geocaching/connector/ec/ECConnector.java index a266eee..68dbee7 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECConnector.java +++ b/main/src/cgeo/geocaching/connector/ec/ECConnector.java @@ -2,7 +2,6 @@ package cgeo.geocaching.connector.ec; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; @@ -16,9 +15,9 @@ import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.connector.gc.MapTokens; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.SettingsActivity; import cgeo.geocaching.utils.CancellableHandler; @@ -37,13 +36,18 @@ import java.util.regex.Pattern; public class ECConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ILogin, ICredentials { + @NonNull private static final String CACHE_URL = "http://extremcaching.com/index.php/output-2/"; /** * Pattern for EC codes */ + @NonNull private final static Pattern PATTERN_EC_CODE = Pattern.compile("EC[0-9]+", Pattern.CASE_INSENSITIVE); + private final CgeoApplication app = CgeoApplication.getInstance(); + + @NonNull private final ECLogin ecLogin = ECLogin.getInstance(); private ECConnector() { @@ -57,27 +61,30 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, private static final @NonNull ECConnector INSTANCE = new ECConnector(); } - public static @NonNull - ECConnector getInstance() { + @NonNull + public static ECConnector getInstance() { return Holder.INSTANCE; } @Override - public boolean canHandle(@NonNull String geocode) { + public boolean canHandle(@NonNull final String geocode) { return ECConnector.PATTERN_EC_CODE.matcher(geocode).matches(); } @Override - public String getCacheUrl(@NonNull Geocache cache) { + @NonNull + public String getCacheUrl(@NonNull final Geocache cache) { return CACHE_URL + cache.getGeocode().replace("EC", ""); } @Override + @NonNull public String getName() { return "extremcaching.com"; } @Override + @NonNull public String getHost() { return "extremcaching.com"; } @@ -95,31 +102,28 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public SearchResult searchByViewport(@NonNull Viewport viewport, final MapTokens tokens) { + @NonNull + public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) { final Collection<Geocache> caches = ECApi.searchByBBox(viewport); - if (caches == null) { - return null; - } final SearchResult searchResult = new SearchResult(caches); return searchResult.filterSearchResults(false, false, Settings.getCacheType()); } @Override - public SearchResult searchByCenter(@NonNull Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) { + @NonNull + public SearchResult searchByCenter(@NonNull final Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) { final Collection<Geocache> caches = ECApi.searchByCenter(center); - if (caches == null) { - return null; - } final SearchResult searchResult = new SearchResult(caches); return searchResult.filterSearchResults(false, false, Settings.getCacheType()); } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return false; } @Override + @NonNull protected String getCacheUrlPrefix() { return CACHE_URL; } @@ -130,7 +134,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean login(Handler handler, Context fromActivity) { + public boolean login(final Handler handler, final Context fromActivity) { // login final StatusCode status = ecLogin.login(); @@ -167,7 +171,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public int getCacheMapMarkerId(boolean disabled) { + public int getCacheMapMarkerId(final boolean disabled) { final String icons = Settings.getECIconSet(); if (StringUtils.equals(icons, "1")) { return disabled ? R.drawable.marker_disabled_other : R.drawable.marker_other; @@ -176,6 +180,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, } @Override + @NonNull public String getLicenseText(final @NonNull Geocache cache) { // NOT TO BE TRANSLATED return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, CC BY-NC-ND 3.0, alle Logeinträge © jeweiliger Autor"; @@ -187,17 +192,19 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean canLog(Geocache cache) { + public boolean canLog(@NonNull final Geocache cache) { return true; } @Override - public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) { + @NonNull + public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) { return new ECLoggingManager(activity, this, cache); } @Override - public List<LogType> getPossibleLogTypes(Geocache geocache) { + @NonNull + public List<LogType> getPossibleLogTypes(@NonNull final Geocache geocache) { final List<LogType> logTypes = new ArrayList<>(); if (geocache.isEventCache()) { logTypes.add(LogType.WILL_ATTEND); @@ -227,4 +234,14 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, return R.string.pref_ecpassword; } + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + final String geocode = "EC" + StringUtils.substringAfter(url, "extremcaching.com/index.php/output-2/"); + if (canHandle(geocode)) { + return geocode; + } + return super.getGeocodeFromUrl(url); + } + } diff --git a/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java b/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java index ded2d71..34c3d1b 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/ec/ECLoggingManager.java @@ -7,19 +7,28 @@ import cgeo.geocaching.connector.AbstractLoggingManager; import cgeo.geocaching.connector.ImageResult; import cgeo.geocaching.connector.LogResult; import cgeo.geocaching.enumerations.LogType; +import cgeo.geocaching.enumerations.StatusCode; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import android.net.Uri; import java.util.Calendar; import java.util.List; -public class ECLoggingManager extends AbstractLoggingManager { +class ECLoggingManager extends AbstractLoggingManager { + @NonNull private final ECConnector connector; + + @NonNull private final Geocache cache; - private LogCacheActivity activity; - public ECLoggingManager(final LogCacheActivity activity, final ECConnector connector, final Geocache cache) { + @NonNull + private final LogCacheActivity activity; + + ECLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final ECConnector connector, @NonNull final Geocache cache) { this.connector = connector; this.cache = cache; this.activity = activity; @@ -31,16 +40,19 @@ public class ECLoggingManager extends AbstractLoggingManager { } @Override - public final LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) { + @NonNull + public final LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) { return ECApi.postLog(cache, logType, date, log); } @Override + @NonNull public final ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) { - return null; + return new ImageResult(StatusCode.LOG_POST_ERROR, ""); } @Override + @NonNull public List<LogType> getPossibleLogTypes() { return connector.getPossibleLogTypes(cache); } diff --git a/main/src/cgeo/geocaching/connector/ec/ECLogin.java b/main/src/cgeo/geocaching/connector/ec/ECLogin.java index 012bdc9..94b450b 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECLogin.java +++ b/main/src/cgeo/geocaching/connector/ec/ECLogin.java @@ -7,34 +7,42 @@ import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import ch.boye.httpclientandroidlib.HttpResponse; + +import com.fasterxml.jackson.databind.JsonNode; + import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; + +import java.io.IOException; public class ECLogin extends AbstractLogin { private final CgeoApplication app = CgeoApplication.getInstance(); - protected String sessionId = null; + private String sessionId = null; private ECLogin() { // singleton } private static class SingletonHolder { - private static ECLogin INSTANCE = new ECLogin(); + @NonNull + private final static ECLogin INSTANCE = new ECLogin(); } + @NonNull public static ECLogin getInstance() { return SingletonHolder.INSTANCE; } @Override - protected StatusCode login(boolean retry) { + @NonNull + protected StatusCode login(final boolean retry) { final ImmutablePair<String, String> login = Settings.getCredentials(ECConnector.getInstance()); if (StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) { @@ -46,9 +54,9 @@ public class ECLogin extends AbstractLogin { setActualStatus(app.getString(R.string.init_login_popup_working)); final Parameters params = new Parameters("user", login.left, "pass", login.right); - HttpResponse loginResponse = Network.postRequest("https://extremcaching.com/exports/apilogin.php", params); + final HttpResponse loginResponse = Network.postRequest("https://extremcaching.com/exports/apilogin.php", params); - String loginData = Network.getResponseData(loginResponse); + final String loginData = Network.getResponseData(loginResponse); if (StringUtils.isBlank(loginData)) { Log.e("ECLogin.login: Failed to retrieve login data"); @@ -80,10 +88,9 @@ public class ECLogin extends AbstractLogin { /** * Check if the user has been logged in when he retrieved the data. * - * @param data * @return <code>true</code> if user is logged in, <code>false</code> otherwise */ - public boolean getLoginStatus(@Nullable final String data) { + private boolean getLoginStatus(@Nullable final String data) { if (StringUtils.isBlank(data) || StringUtils.equals(data, "[]")) { Log.e("ECLogin.getLoginStatus: No or empty data given"); return false; @@ -93,18 +100,18 @@ public class ECLogin extends AbstractLogin { setActualStatus(app.getString(R.string.init_login_popup_ok)); try { - final JSONObject json = new JSONObject(data); + final JsonNode json = JsonUtils.reader.readTree(data); - final String sid = json.getString("sid"); + final String sid = json.get("sid").asText(); if (!StringUtils.isBlank(sid)) { sessionId = sid; setActualLoginStatus(true); - setActualUserName(json.getString("username")); - setActualCachesFound(json.getInt("found")); + setActualUserName(json.get("username").asText()); + setActualCachesFound(json.get("found").asInt()); return true; } resetLoginStatus(); - } catch (final JSONException e) { + } catch (IOException | NullPointerException e) { Log.e("ECLogin.getLoginStatus", e); } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index 3b7c31e..b38d2e4 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -3,7 +3,6 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; @@ -20,10 +19,11 @@ import cgeo.geocaching.connector.capability.ISearchByGeocode; import cgeo.geocaching.connector.capability.ISearchByKeyword; import cgeo.geocaching.connector.capability.ISearchByOwner; import cgeo.geocaching.connector.capability.ISearchByViewPort; +import cgeo.geocaching.connector.capability.IgnoreCapability; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; @@ -48,20 +48,24 @@ import java.io.File; import java.util.List; import java.util.regex.Pattern; -public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ISearchByKeyword, ILogin, ICredentials, ISearchByOwner, ISearchByFinder, FieldNotesCapability { +public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ISearchByKeyword, ILogin, ICredentials, ISearchByOwner, ISearchByFinder, FieldNotesCapability, IgnoreCapability { + @NonNull private static final String CACHE_URL_SHORT = "http://coord.info/"; // Double slash is used to force open in browser + @NonNull private static final String CACHE_URL_LONG = "http://www.geocaching.com/seek/cache_details.aspx?wp="; /** * Pocket queries downloaded from the website use a numeric prefix. The pocket query creator Android app adds a * verbatim "pocketquery" prefix. */ + @NonNull private static final Pattern GPX_ZIP_FILE_PATTERN = Pattern.compile("((\\d{7,})|(pocketquery))" + "(_.+)?" + "\\.zip", Pattern.CASE_INSENSITIVE); /** * Pattern for GC codes */ + @NonNull private final static Pattern PATTERN_GC_CODE = Pattern.compile("GC[0-9A-Z]+", Pattern.CASE_INSENSITIVE); private GCConnector() { @@ -75,23 +79,25 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, private static final @NonNull GCConnector INSTANCE = new GCConnector(); } - public static @NonNull - GCConnector getInstance() { + @NonNull + public static GCConnector getInstance() { return Holder.INSTANCE; } @Override - public boolean canHandle(@NonNull String geocode) { + public boolean canHandle(@NonNull final String geocode) { return GCConnector.PATTERN_GC_CODE.matcher(geocode).matches(); } @Override - public String getLongCacheUrl(@NonNull Geocache cache) { + @NonNull + public String getLongCacheUrl(@NonNull final Geocache cache) { return CACHE_URL_LONG + cache.getGeocode(); } @Override - public String getCacheUrl(@NonNull Geocache cache) { + @NonNull + public String getCacheUrl(@NonNull final Geocache cache) { return CACHE_URL_SHORT + cache.getGeocode(); } @@ -121,21 +127,24 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) { + @NonNull + public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) { return new GCLoggingManager(activity, cache); } @Override - public boolean canLog(Geocache cache) { + public boolean canLog(@NonNull final Geocache cache) { return StringUtils.isNotBlank(cache.getCacheId()); } @Override + @NonNull public String getName() { return "geocaching.com"; } @Override + @NonNull public String getHost() { return "www.geocaching.com"; } @@ -178,28 +187,29 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public SearchResult searchByViewport(@NonNull Viewport viewport, final MapTokens tokens) { + @NonNull + public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) { return GCMap.searchByViewport(viewport, tokens); } @Override - public boolean isZippedGPXFile(final String fileName) { + public boolean isZippedGPXFile(@NonNull final String fileName) { return GPX_ZIP_FILE_PATTERN.matcher(fileName).matches(); } @Override - public boolean isReliableLatLon(boolean cacheHasReliableLatLon) { + public boolean isReliableLatLon(final boolean cacheHasReliableLatLon) { return cacheHasReliableLatLon; } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { final String user = Settings.getUsername(); return StringUtils.isNotEmpty(user) && StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), user); } @Override - public boolean addToWatchlist(Geocache cache) { + public boolean addToWatchlist(@NonNull final Geocache cache) { final boolean added = GCParser.addToWatchlist(cache); if (added) { DataStore.saveChangedCache(cache); @@ -208,7 +218,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean removeFromWatchlist(Geocache cache) { + public boolean removeFromWatchlist(@NonNull final Geocache cache) { final boolean removed = GCParser.removeFromWatchlist(cache); if (removed) { DataStore.saveChangedCache(cache); @@ -226,7 +236,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, * @return <code>true</code> if the cache was successfully added, <code>false</code> otherwise */ - public static boolean addToFavorites(Geocache cache) { + public static boolean addToFavorites(final Geocache cache) { final boolean added = GCParser.addToFavorites(cache); if (added) { DataStore.saveChangedCache(cache); @@ -244,7 +254,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, * @return <code>true</code> if the cache was successfully added, <code>false</code> otherwise */ - public static boolean removeFromFavorites(Geocache cache) { + public static boolean removeFromFavorites(final Geocache cache) { final boolean removed = GCParser.removeFromFavorites(cache); if (removed) { DataStore.saveChangedCache(cache); @@ -253,7 +263,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) { + public boolean uploadModifiedCoordinates(@NonNull final Geocache cache, @NonNull final Geopoint wpt) { final boolean uploaded = GCParser.uploadModifiedCoordinates(cache, wpt); if (uploaded) { DataStore.saveChangedCache(cache); @@ -262,7 +272,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean deleteModifiedCoordinates(Geocache cache) { + public boolean deleteModifiedCoordinates(@NonNull final Geocache cache) { final boolean deleted = GCParser.deleteModifiedCoordinates(cache); if (deleted) { DataStore.saveChangedCache(cache); @@ -271,7 +281,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean uploadPersonalNote(Geocache cache) { + public boolean uploadPersonalNote(@NonNull final Geocache cache) { final boolean uploaded = GCParser.uploadPersonalNote(cache); if (uploaded) { DataStore.saveChangedCache(cache); @@ -280,31 +290,34 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public SearchResult searchByCenter(@NonNull Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) { + public SearchResult searchByCenter(@NonNull final Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) { return GCParser.searchByCoords(center, Settings.getCacheType(), Settings.isShowCaptcha(), recaptchaReceiver); } @Override - public boolean supportsFavoritePoints(final Geocache cache) { + public boolean supportsFavoritePoints(@NonNull final Geocache cache) { return !cache.getType().isEvent(); } @Override + @NonNull protected String getCacheUrlPrefix() { - return null; // UNUSED + return StringUtils.EMPTY; // UNUSED } @Override - public String getGeocodeFromUrl(String url) { + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + final String noQueryString = StringUtils.substringBefore(url, "?"); // coord.info URLs - String code = StringUtils.substringAfterLast(url, "coord.info/"); - if (code != null && canHandle(code)) { - return code; + final String afterCoord = StringUtils.substringAfterLast(noQueryString, "coord.info/"); + if (canHandle(afterCoord)) { + return afterCoord; } // expanded geocaching.com URLs - code = StringUtils.substringBetween(url, "/geocache/", "_"); - if (code != null && canHandle(code)) { - return code; + final String afterGeocache = StringUtils.substringBetween(noQueryString, "/geocache/", "_"); + if (afterGeocache != null && canHandle(afterGeocache)) { + return afterGeocache; } return null; } @@ -315,7 +328,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public int getCacheMapMarkerId(boolean disabled) { + public int getCacheMapMarkerId(final boolean disabled) { if (disabled) { return R.drawable.marker_disabled; } @@ -323,14 +336,10 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean login(Handler handler, Context fromActivity) { + public boolean login(final Handler handler, final Context fromActivity) { // login final StatusCode status = GCLogin.getInstance().login(); - if (status == StatusCode.NO_ERROR) { - GCLogin.detectGcCustomDate(); - } - if (CgeoApplication.getInstance().showLoginToast && handler != null) { handler.sendMessage(handler.obtainMessage(0, status)); CgeoApplication.getInstance().showLoginToast = false; @@ -344,6 +353,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override + public void logout() { + GCLogin.getInstance().logout(); + } + + @Override public String getUserName() { return GCLogin.getInstance().getActualUserName(); } @@ -364,7 +378,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getWaypointGpxId(String prefix, String geocode) { + public String getWaypointGpxId(final String prefix, @NonNull final String geocode) { String gpxId = prefix; if (StringUtils.isNotBlank(geocode) && geocode.length() > 2) { gpxId += geocode.substring(2); @@ -373,7 +387,8 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getWaypointPrefix(String name) { + @NonNull + public String getWaypointPrefix(final String name) { String prefix = name; if (StringUtils.isNotBlank(prefix) && prefix.length() >= 2) { prefix = name.substring(0, 2); @@ -382,7 +397,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public SearchResult searchByKeyword(@NonNull String keyword, final @NonNull RecaptchaReceiver recaptchaReceiver) { + public SearchResult searchByKeyword(@NonNull final String keyword, final @NonNull RecaptchaReceiver recaptchaReceiver) { return GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha(), recaptchaReceiver); } @@ -399,18 +414,18 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, @Override public @NonNull List<UserAction> getUserActions() { - List<UserAction> actions = super.getUserActions(); + final List<UserAction> actions = super.getUserActions(); actions.add(new UserAction(R.string.user_menu_open_browser, new Action1<UserAction.Context>() { @Override - public void call(cgeo.geocaching.connector.UserAction.Context context) { + public void call(final cgeo.geocaching.connector.UserAction.Context context) { context.activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(context.userName)))); } })); actions.add(new UserAction(R.string.user_menu_send_message, new Action1<UserAction.Context>() { @Override - public void call(cgeo.geocaching.connector.UserAction.Context context) { + public void call(final cgeo.geocaching.connector.UserAction.Context context) { try { context.activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(context.userName)))); } catch (final ActivityNotFoundException e) { @@ -433,7 +448,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public boolean uploadFieldNotes(final File exportFile) { + public boolean uploadFieldNotes(@NonNull final File exportFile) { if (!GCLogin.getInstance().isActualLoginStatus()) { // no need to upload (possibly large file) if we're not logged in final StatusCode loginState = GCLogin.getInstance().login(); @@ -468,4 +483,14 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, return true; } + @Override + public boolean canIgnoreCache(@NonNull final Geocache cache) { + return StringUtils.isNotEmpty(cache.getType().wptTypeId); + } + + @Override + public void ignoreCache(@NonNull final Geocache cache) { + GCParser.ignoreCache(cache); + } + } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java index 3f16156..1b4c5a6 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java @@ -15,172 +15,175 @@ import java.util.regex.Pattern; public final class GCConstants { static final String GC_URL = "http://www.geocaching.com/"; - static final String GC_TILE_URL = "http://tiles.geocaching.com/"; + private static final String GC_TILE_URL = "http://tiles.geocaching.com/"; /** Live Map */ - public final static @NonNull String URL_LIVE_MAP = GC_URL + "map/default.aspx"; + final static @NonNull String URL_LIVE_MAP = GC_URL + "map/default.aspx"; /** Live Map pop-up */ - public final static @NonNull String URL_LIVE_MAP_DETAILS = GC_TILE_URL + "map.details"; + final static @NonNull String URL_LIVE_MAP_DETAILS = GC_TILE_URL + "map.details"; /** Caches in a tile */ - public final static @NonNull String URL_MAP_INFO = GC_TILE_URL + "map.info"; + final static @NonNull String URL_MAP_INFO = GC_TILE_URL + "map.info"; /** Tile itself */ - public final static @NonNull String URL_MAP_TILE = GC_TILE_URL + "map.png"; + final static @NonNull String URL_MAP_TILE = GC_TILE_URL + "map.png"; + /** Format used by geocaching.com when user is not logged in. */ + public static final String DEFAULT_GC_DATE = "MM/dd/yyyy"; /** * Patterns for parsing the result of a (detailed) search */ - public final static Pattern PATTERN_HINT = Pattern.compile("<div id=\"div_hint\"[^>]*>(.*?)</div>", Pattern.DOTALL); - public final static Pattern PATTERN_DESC = Pattern.compile("<span id=\"ctl00_ContentBody_LongDescription\">(.*?)</span>\\s*</div>\\s*<p>\\s*</p>\\s*<p id=\"ctl00_ContentBody_hints\">", Pattern.DOTALL); - public final static Pattern PATTERN_SHORTDESC = Pattern.compile("<span id=\"ctl00_ContentBody_ShortDescription\">(.*?)</span>\\s*</div>", Pattern.DOTALL); - public final static Pattern PATTERN_GEOCODE = Pattern.compile("class=\"CoordInfoCode\">(GC[0-9A-Z]+)</span>"); - public final static Pattern PATTERN_CACHEID = Pattern.compile("/seek/log\\.aspx\\?ID=(\\d+)"); - public final static Pattern PATTERN_GUID = Pattern.compile(Pattern.quote("&wid=") + "([0-9a-z\\-]+)" + Pattern.quote("&")); - public final static Pattern PATTERN_SIZE = Pattern.compile("<div id=\"ctl00_ContentBody_size\" class=\"CacheSize[^\"]*\">[^<]*<p[^>]*>[^S]*Size[^:]*:[^<]*<span[^>]*>[^<]*<img src=\"[^\"]*/icons/container/[a-z_]+\\.gif\" alt=\"\\w+: ([^\"]+)\"[^>]*>[^<]*<small>[^<]*</small>[^<]*</span>[^<]*</p>"); - public final static Pattern PATTERN_LATLON = Pattern.compile("<span id=\"uxLatLon\"[^>]*>(.*?)</span>"); - public final static Pattern PATTERN_LATLON_ORIG = Pattern.compile("\\{\"isUserDefined\":true[^}]+?\"oldLatLngDisplay\":\"([^\"]+)\"\\}"); - public final static Pattern PATTERN_LOCATION = Pattern.compile(Pattern.quote("<span id=\"ctl00_ContentBody_Location\">In ") + "(?:<a href=[^>]*>)?(.*?)<"); - public final static Pattern PATTERN_PERSONALNOTE = Pattern.compile("<span id=\"cache_note\"[^>]*>(.*?)</span>", Pattern.DOTALL); - public final static Pattern PATTERN_NAME = Pattern.compile("<span id=\"ctl00_ContentBody_CacheName\">(.*?)</span>"); - public final static Pattern PATTERN_DIFFICULTY = Pattern.compile("<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\""); - public final static Pattern PATTERN_TERRAIN = Pattern.compile("<span id=\"ctl00_ContentBody_Localize[\\d]+\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\""); - public final static Pattern PATTERN_OWNER_USERID = Pattern.compile("other caches <a href=\"/seek/nearest\\.aspx\\?u=(.*?)\">hidden</a> or"); - public final static Pattern PATTERN_FOUND = Pattern.compile("ctl00_ContentBody_GeoNav_logText\">(Found It|Attended)"); - public final static Pattern PATTERN_FOUND_ALTERNATIVE = Pattern.compile("<div class=\"StatusInformationWidget FavoriteWidget\""); - public final static Pattern PATTERN_FOUND_DATE = Pattern.compile(">Logged on: ([^<]+?)<"); - public final static Pattern PATTERN_OWNER_DISPLAYNAME = Pattern.compile("<div id=\"ctl00_ContentBody_mcd1\">[^<]+<a href=\"[^\"]+\">([^<]+)</a>"); - public final static Pattern PATTERN_TYPE = Pattern.compile("<a href=\"/seek/nearest.aspx\\?tx=([0-9a-f-]+)"); - public final static Pattern PATTERN_HIDDEN = Pattern.compile("<div id=\"ctl00_ContentBody_mcd2\">\\W*Hidden[\\s:]*([^<]+?)</div>"); - public final static Pattern PATTERN_HIDDENEVENT = Pattern.compile("Event\\s*Date\\s*:\\s*([^<]+)<div id=\"calLinks\">", Pattern.DOTALL); - public final static Pattern PATTERN_FAVORITE = Pattern.compile("<div id=\"pnlFavoriteCache\">"); // without 'class="hideMe"' inside the tag ! - public final static Pattern PATTERN_FAVORITECOUNT = Pattern.compile("<span class=\"favorite-value\">\\D*([0-9]+?)\\D*</span>"); - public final static Pattern PATTERN_COUNTLOGS = Pattern.compile("<span id=\"ctl00_ContentBody_lblFindCounts\"><p(.+?)</p></span>"); - public final static Pattern PATTERN_LOGBOOK = Pattern.compile("initalLogs = (\\{.+\\});"); // The "inital" typo really comes from gc.com site + final static Pattern PATTERN_HINT = Pattern.compile("<div id=\"div_hint\"[^>]*>(.*?)</div>", Pattern.DOTALL); + final static Pattern PATTERN_DESC = Pattern.compile("<span id=\"ctl00_ContentBody_LongDescription\">(.*?)</span>\\s*</div>\\s*<p>\\s*</p>\\s*<p id=\"ctl00_ContentBody_hints\">", Pattern.DOTALL); + final static Pattern PATTERN_SHORTDESC = Pattern.compile("<span id=\"ctl00_ContentBody_ShortDescription\">(.*?)</span>\\s*</div>", Pattern.DOTALL); + final static Pattern PATTERN_GEOCODE = Pattern.compile("class=\"CoordInfoCode\">(GC[0-9A-Z]+)</span>"); + final static Pattern PATTERN_CACHEID = Pattern.compile("/seek/log\\.aspx\\?ID=(\\d+)"); + final static Pattern PATTERN_GUID = Pattern.compile(Pattern.quote("&wid=") + "([0-9a-z\\-]+)" + Pattern.quote("&")); + final static Pattern PATTERN_SIZE = Pattern.compile("<div id=\"ctl00_ContentBody_size\" class=\"CacheSize[^\"]*\">[^<]*<p[^>]*>[^S]*Size[^:]*:[^<]*<span[^>]*>[^<]*<img src=\"[^\"]*/icons/container/[a-z_]+\\.gif\" alt=\"\\w+: ([^\"]+)\"[^>]*>[^<]*<small>[^<]*</small>[^<]*</span>[^<]*</p>"); + final static Pattern PATTERN_LATLON = Pattern.compile("<span id=\"uxLatLon\"[^>]*>(.*?)</span>"); + final static Pattern PATTERN_LATLON_ORIG = Pattern.compile("\\{\"isUserDefined\":true[^}]+?\"oldLatLngDisplay\":\"([^\"]+)\"\\}"); + final static Pattern PATTERN_LOCATION = Pattern.compile(Pattern.quote("<span id=\"ctl00_ContentBody_Location\">In ") + "(?:<a href=[^>]*>)?(.*?)<"); + final static Pattern PATTERN_PERSONALNOTE = Pattern.compile("<span id=\"cache_note\"[^>]*>(.*?)</span>", Pattern.DOTALL); + final static Pattern PATTERN_NAME = Pattern.compile("<span id=\"ctl00_ContentBody_CacheName\">(.*?)</span>"); + final static Pattern PATTERN_DIFFICULTY = Pattern.compile("<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\""); + final static Pattern PATTERN_TERRAIN = Pattern.compile("<span id=\"ctl00_ContentBody_Localize[\\d]+\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\""); + final static Pattern PATTERN_OWNER_USERID = Pattern.compile("other caches <a href=\"/seek/nearest\\.aspx\\?u=(.*?)\">hidden</a> or"); + final static Pattern PATTERN_FOUND = Pattern.compile("ctl00_ContentBody_GeoNav_logText\">(Found It|Attended)"); + final static Pattern PATTERN_FOUND_ALTERNATIVE = Pattern.compile("<div class=\"StatusInformationWidget FavoriteWidget\""); + final static Pattern PATTERN_OWNER_DISPLAYNAME = Pattern.compile("<div id=\"ctl00_ContentBody_mcd1\">[^<]+<a href=\"[^\"]+\">([^<]+)</a>"); + final static Pattern PATTERN_TYPE = Pattern.compile("<a href=\"/seek/nearest.aspx\\?tx=([0-9a-f-]+)"); + final static Pattern PATTERN_HIDDEN = Pattern.compile("<div id=\"ctl00_ContentBody_mcd2\">\\W*Hidden[\\s:]*([^<]+?)</div>"); + final static Pattern PATTERN_HIDDENEVENT = Pattern.compile("Event\\s*Date\\s*:\\s*([^<]+)<div id=\"calLinks\">", Pattern.DOTALL); + final static Pattern PATTERN_FAVORITE = Pattern.compile("<div id=\"pnlFavoriteCache\">"); // without 'class="hideMe"' inside the tag ! + final static Pattern PATTERN_FAVORITECOUNT = Pattern.compile("<span class=\"favorite-value\">\\D*([0-9]+?)\\D*</span>"); + final static Pattern PATTERN_COUNTLOGS = Pattern.compile("<span id=\"ctl00_ContentBody_lblFindCounts\"><p(.+?)</p></span>"); /** Two groups ! */ - public final static Pattern PATTERN_COUNTLOG = Pattern.compile("<img src=\"/images/logtypes/([0-9]+)\\.png\"[^>]+> (\\d*[,.]?\\d+)"); - public static final Pattern PATTERN_PREMIUMMEMBERS = Pattern.compile("<p class=\"Warning NoBottomSpacing\">This is a Premium Member Only cache.</p>"); - public final static Pattern PATTERN_ATTRIBUTES = Pattern.compile("Attributes\\s*</h3>[^<]*<div class=\"WidgetBody\">((?:[^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+?)[^<]*<p"); + final static Pattern PATTERN_COUNTLOG = Pattern.compile("<img src=\"/images/logtypes/([0-9]+)\\.png\"[^>]+> (\\d*[,.]?\\d+)"); + static final Pattern PATTERN_PREMIUMMEMBERS = Pattern.compile("<p class=\"Warning NoBottomSpacing\">This is a Premium Member Only cache.</p>"); + final static Pattern PATTERN_ATTRIBUTES = Pattern.compile("Attributes\\s*</h3>[^<]*<div class=\"WidgetBody\">((?:[^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+?)[^<]*<p"); /** Two groups ! */ - public final static Pattern PATTERN_ATTRIBUTESINSIDE = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+?)\""); - public final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://imgcdn\\.geocaching\\.com[^.]+\\.(jpg|jpeg|png|gif))\"[^>]+>([^<]+)</a>(?:<br />([^<]+)<br /><br />)?"); - public final static Pattern PATTERN_INVENTORY = Pattern.compile("<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">\\W*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?"); - public final static Pattern PATTERN_INVENTORYINSIDE = Pattern.compile("[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>"); - public final static Pattern PATTERN_WATCHLIST = Pattern.compile(Pattern.quote("watchlist.aspx") + ".{1,50}" + Pattern.quote("action=rem")); - public final static Pattern PATTERN_RELATED_WEB_PAGE = Pattern.compile("id=\"ctl00_ContentBody_uxCacheUrl\" title=\"Related Web Page\" href=\"(.*?)\">"); + final static Pattern PATTERN_ATTRIBUTESINSIDE = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+?)\""); + final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://img(?:cdn)?\\.geocaching\\.com[^.]+\\.(jpg|jpeg|png|gif))\"[^>]+>([^<]+)</a>(?:<br />([^<]+)<br /><br />)?"); + final static Pattern PATTERN_INVENTORY = Pattern.compile("<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">\\W*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?"); + final static Pattern PATTERN_INVENTORYINSIDE = Pattern.compile("[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>"); + final static Pattern PATTERN_WATCHLIST = Pattern.compile(Pattern.quote("watchlist.aspx") + ".{1,50}" + Pattern.quote("action=rem")); + final static Pattern PATTERN_RELATED_WEB_PAGE = Pattern.compile("id=\"ctl00_ContentBody_uxCacheUrl\" title=\"Related Web Page\" href=\"(.*?)\">"); // Info box top-right - public static final Pattern PATTERN_LOGIN_NAME = Pattern.compile("\"SignedInProfileLink\">(.*?)</a>"); - public static final Pattern PATTERN_MEMBER_STATUS = Pattern.compile("<span id=\"ctl00_litPMLevel\">([^<]+)</span>"); - public static final String MEMBER_STATUS_RENEW = "<a id=\"ctl00_hlRenew"; - public static final String MEMBER_STATUS_PM = "Premium Member"; + public static final Pattern PATTERN_LOGIN_NAME = Pattern.compile("class=\"li-user-info\"[^>]*>.*?<span>(.*?)</span>", Pattern.DOTALL); + public static final Pattern PATTERN_MEMBERSHIP = Pattern.compile("<dl class=\"membership-details\">.*?<dt>Membership</dt>.*?<dd>\\s*(\\p{Alpha}+)\\s*</dd>", Pattern.DOTALL); + public static final String MEMBER_STATUS_PREMIUM = "Premium"; + public static final String MEMBER_STATUS_CHARTER = "Charter"; /** Use replaceAll("[,.]","") on the resulting string before converting to an int */ - public static final Pattern PATTERN_CACHES_FOUND = Pattern.compile("<strong[^>]*>.*?([\\d,.]+) Caches? Found", Pattern.DOTALL); - public static final Pattern PATTERN_AVATAR_IMAGE_PROFILE_PAGE = Pattern.compile("src=\"(https?://(imgcdn\\.geocaching\\.com|[^>\"]+\\.cloudfront\\.net)/avatar/[0-9a-f-]+\\.jpg)\"[^>]*alt=\""); - public static final Pattern PATTERN_LOGIN_NAME_LOGIN_PAGE = Pattern.compile("ctl00_ContentBody_lbUsername\">.*<strong>(.*)</strong>"); - public static final Pattern PATTERN_CUSTOMDATE = Pattern.compile("<option selected=\"selected\" value=\"([ /.Mdy-]+)\">"); - public static final Pattern PATTERN_MAP_LOGGED_IN = Pattern.compile("<a href=\"https?://www.geocaching.com/my/\" class=\"CommonUsername\""); + static final Pattern PATTERN_CACHES_FOUND = Pattern.compile("<span[^>]*>.*?([\\d,.]+) Finds?", Pattern.DOTALL); + static final Pattern PATTERN_AVATAR_IMAGE_PROFILE_PAGE = Pattern.compile("src=\"(https?://(img(?:cdn)?\\.geocaching\\.com|[^>\"]+\\.cloudfront\\.net)/avatar/[0-9a-f-]+\\.jpg)\"[^>]*alt=\""); + static final Pattern PATTERN_LOGIN_NAME_LOGIN_PAGE = Pattern.compile("ctl00_ContentBody_lbUsername\">.*<strong>(.*)</strong>"); + static final Pattern PATTERN_CUSTOMDATE = Pattern.compile("<option selected=\"selected\" value=\"([ /.Mdy-]+)\">"); + static final Pattern PATTERN_HOME_LOCATION = Pattern.compile("<input class=\"search-coordinates\"[^>]* value=\"(.*?)\""); + static final Pattern PATTERN_MAP_LOGGED_IN = Pattern.compile("<a href=\"https?://www.geocaching.com/my/\" class=\"CommonUsername\""); /** * Patterns for parsing trackables */ - public final static Pattern PATTERN_TRACKABLE_GUID = Pattern.compile("<a id=\"ctl00_ContentBody_lnkPrint\" title=\"[^\"]*\" href=\".*sheet\\.aspx\\?guid=([a-z0-9\\-]+)\"[^>]*>[^<]*</a>"); - public final static Pattern PATTERN_TRACKABLE_GEOCODE = Pattern.compile("<strong>(TB[0-9A-Z]+)[^<]*</strong> to reference this item."); + final static Pattern PATTERN_TRACKABLE_GUID = Pattern.compile("<a id=\"ctl00_ContentBody_lnkPrint\" title=\"[^\"]*\" href=\".*sheet\\.aspx\\?guid=([a-z0-9\\-]+)\"[^>]*>[^<]*</a>"); + final static Pattern PATTERN_TRACKABLE_GEOCODE = Pattern.compile("<strong>(TB[0-9A-Z]+)[^<]*</strong> to reference this item."); // multiple error codes, depending on the search term for the trackable code - public final static String ERROR_TB_DOES_NOT_EXIST = "does not exist in the system"; - public final static String ERROR_TB_ELEMENT_EXCEPTION = "ElementNotFound Exception"; - public final static String ERROR_TB_ARITHMETIC_OVERFLOW = "operation resulted in an overflow"; - public final static String ERROR_TB_NOT_ACTIVATED = "hasn't been activated"; + final static String ERROR_TB_DOES_NOT_EXIST = "does not exist in the system"; + final static String ERROR_TB_ELEMENT_EXCEPTION = "ElementNotFound Exception"; + final static String ERROR_TB_ARITHMETIC_OVERFLOW = "operation resulted in an overflow"; + final static String ERROR_TB_NOT_ACTIVATED = "hasn't been activated"; /** * some parts of the webpage don't correctly encode the name, therefore this pattern must be checked with a * trackable name that needs HTML encoding */ - public final static Pattern PATTERN_TRACKABLE_NAME = Pattern.compile("<span id=\"ctl00_ContentBody_lbHeading\">(.*?)</span>"); + final static Pattern PATTERN_TRACKABLE_NAME = Pattern.compile("<span id=\"ctl00_ContentBody_lbHeading\">(.*?)</span>"); /** Two groups ! */ - public final static Pattern PATTERN_TRACKABLE_OWNER = Pattern.compile("<a id=\"ctl00_ContentBody_BugDetails_BugOwner\"[^>]+href=\"https?://www.geocaching.com/profile/\\?guid=(.*?)\">(.*?)</a>"); - public final static Pattern PATTERN_TRACKABLE_RELEASES = Pattern.compile("<dt>\\W*Released:[^<]*</dt>[^<]*<dd>[^<]*<span id=\"ctl00_ContentBody_BugDetails_BugReleaseDate\">([^<]+)<\\/span>[^<]*</dd>"); - public final static Pattern PATTERN_TRACKABLE_ORIGIN = Pattern.compile("<dt>\\W*Origin:[^<]*</dt>[^<]*<dd>[^<]*<span id=\"ctl00_ContentBody_BugDetails_BugOrigin\">([^<]+)<\\/span>[^<]*</dd>"); + final static Pattern PATTERN_TRACKABLE_OWNER = Pattern.compile("<a id=\"ctl00_ContentBody_BugDetails_BugOwner\"[^>]+href=\"https?://www.geocaching.com/profile/\\?guid=(.*?)\">(.*?)</a>"); + final static Pattern PATTERN_TRACKABLE_RELEASES = Pattern.compile("<dt>\\W*Released:[^<]*</dt>[^<]*<dd>[^<]*<span id=\"ctl00_ContentBody_BugDetails_BugReleaseDate\">([^<]+)<\\/span>[^<]*</dd>"); + final static Pattern PATTERN_TRACKABLE_ORIGIN = Pattern.compile("<dt>\\W*Origin:[^<]*</dt>[^<]*<dd>[^<]*<span id=\"ctl00_ContentBody_BugDetails_BugOrigin\">([^<]+)<\\/span>[^<]*</dd>"); /** Two groups ! */ - public final static Pattern PATTERN_TRACKABLE_SPOTTEDCACHE = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\" title=\"[^\"]*\" href=\"[^\"]*/seek/cache_details.aspx\\?guid=([a-z0-9\\-]+)\">In ([^<]+)</a>[^<]*</dd>"); + final static Pattern PATTERN_TRACKABLE_SPOTTEDCACHE = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\" title=\"[^\"]*\" href=\"[^\"]*/seek/cache_details.aspx\\?guid=([a-z0-9\\-]+)\">In ([^<]+)</a>[^<]*</dd>"); /** Two groups ! */ - public final static Pattern PATTERN_TRACKABLE_SPOTTEDUSER = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\" href=\"[^\"]*/profile/\\?guid=([a-z0-9\\-]+)\">In the hands of ([^<]+).</a>[^<]*</dd>"); - public final static Pattern PATTERN_TRACKABLE_SPOTTEDUNKNOWN = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\">Unknown Location[^<]*</a>[^<]*</dd>"); - public final static Pattern PATTERN_TRACKABLE_SPOTTEDOWNER = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\">In the hands of the owner[^<]*</a>[^<]*</dd>"); - public final static Pattern PATTERN_TRACKABLE_GOAL = Pattern.compile("<div id=\"TrackableGoal\">[^<]*<p>(.*?)</p>[^<]*</div>", Pattern.DOTALL); + final static Pattern PATTERN_TRACKABLE_SPOTTEDUSER = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\" href=\"[^\"]*/profile/\\?guid=([a-z0-9\\-]+)\">In the hands of ([^<]+).</a>[^<]*</dd>"); + final static Pattern PATTERN_TRACKABLE_SPOTTEDUNKNOWN = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\">Unknown Location[^<]*</a>[^<]*</dd>"); + final static Pattern PATTERN_TRACKABLE_SPOTTEDOWNER = Pattern.compile("<dt>\\W*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\">In the hands of the owner[^<]*</a>[^<]*</dd>"); + final static Pattern PATTERN_TRACKABLE_GOAL = Pattern.compile("<div id=\"TrackableGoal\">[^<]*<p>(.*?)</p>[^<]*</div>", Pattern.DOTALL); /** Four groups */ - public final static Pattern PATTERN_TRACKABLE_DETAILSIMAGE = Pattern.compile("<h3>\\W*About This Item[^<]*</h3>[^<]*<div id=\"TrackableDetails\">([^<]*<p>([^<]*<img id=\"ctl00_ContentBody_BugDetails_BugImage\" class=\"[^\"]+\" src=\"([^\"]+)\"[^>]*>)?[^<]*</p>)?[^<]*<p[^>]*>(.*)</p>[^<]*</div> <div id=\"ctl00_ContentBody_BugDetails_uxAbuseReport\">"); - public final static Pattern PATTERN_TRACKABLE_ICON = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"([^\"]+)\"[^>]*>"); - public final static Pattern PATTERN_TRACKABLE_TYPE = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"[^\"]+\" alt=\"([^\"]+)\"[^>]*>"); - public final static Pattern PATTERN_TRACKABLE_DISTANCE = Pattern.compile("<h4[^>]*\\W*Tracking History \\(([0-9.,]+(km|mi))[^\\)]*\\)"); - public final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("<tr class=\"Data BorderTop .+?/images/logtypes/([^.]+)\\.png[^>]+> ([^<]+)</td>.+?guid.+?>([^<]+)</a>.+?(?:guid=([^\"]+)\">(<span[^>]+>)?([^<]+)</.+?)?<td colspan=\"4\">\\s*<div>(.*?)</div>\\s*(?:<ul.+?ul>)?\\s*</td>\\s*</tr>"); - public final static Pattern PATTERN_TRACKABLE_LOG_IMAGES = Pattern.compile("<li><a href=\"([^\"]+)\".+?LogImgTitle.+?>([^<]+)</"); + final static Pattern PATTERN_TRACKABLE_DETAILSIMAGE = Pattern.compile("<h3>\\W*About This Item[^<]*</h3>[^<]*<div id=\"TrackableDetails\">([^<]*<p>([^<]*<img id=\"ctl00_ContentBody_BugDetails_BugImage\" class=\"[^\"]+\" src=\"([^\"]+)\"[^>]*>)?[^<]*</p>)?[^<]*<p[^>]*>(.*)</p>[^<]*</div> <div id=\"ctl00_ContentBody_BugDetails_uxAbuseReport\">"); + final static Pattern PATTERN_TRACKABLE_ICON = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"([^\"]+)\"[^>]*>"); + final static Pattern PATTERN_TRACKABLE_TYPE = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"[^\"]+\" alt=\"([^\"]+)\"[^>]*>"); + final static Pattern PATTERN_TRACKABLE_DISTANCE = Pattern.compile("<h4[^>]*\\W*Tracking History \\(([0-9.,]+(km|mi))[^\\)]*\\)"); + final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("<tr class=\"Data BorderTop .+?/images/logtypes/([^.]+)\\.png[^>]+> ([^<]+)</td>.+?guid.+?>([^<]+)</a>.+?(?:guid=([^\"]+)\">(<span[^>]+>)?([^<]+)</.+?)?<td colspan=\"4\">\\s*<div>(.*?)</div>\\s*(?:<ul.+?ul>)?\\s*</td>\\s*</tr>"); + final static Pattern PATTERN_TRACKABLE_LOG_IMAGES = Pattern.compile("<li><a href=\"([^\"]+)\".+?LogImgTitle.+?>([^<]*)</"); /** * Patterns for parsing the result of a search (next) */ - public final static Pattern PATTERN_SEARCH_TYPE = Pattern.compile("<td class=\"Merge\">.*?<img src=\"[^\"]*/images/wpttypes/[^.]+\\.gif\" alt=\"([^\"]+)\" title=\"[^\"]+\"[^>]*>[^<]*</a>"); - public final static Pattern PATTERN_SEARCH_GUIDANDDISABLED = Pattern.compile("SearchResultsWptType.*?<a href=\"[^\"]*\" class=\"lnk ([^\"]*)\"><span>([^<]*)</span>[^|]*[|][^|]*[|]([^<]*)<"); + final static Pattern PATTERN_SEARCH_TYPE = Pattern.compile("<td class=\"Merge\">.*?<img src=\"[^\"]*/images/wpttypes/[^.]+\\.gif\" alt=\"([^\"]+)\" title=\"[^\"]+\"[^>]*>[^<]*</a>"); + final static Pattern PATTERN_SEARCH_GUIDANDDISABLED = Pattern.compile("SearchResultsWptType.*?<a href=\"[^\"]*\" class=\"lnk ([^\"]*)\"><span>([^<]*)</span>[^|]*[|][^|]*[|]([^<]*)<"); /** Two groups **/ - public final static Pattern PATTERN_SEARCH_TRACKABLES = Pattern.compile("<a id=\"ctl00_ContentBody_dlResults_ctl[0-9]+_uxTravelBugList\" class=\"tblist\" data-tbcount=\"([0-9]+)\" data-id=\"[^\"]*\"[^>]*>(.*)</a>"); + final static Pattern PATTERN_SEARCH_TRACKABLES = Pattern.compile("<a id=\"ctl00_ContentBody_dlResults_ctl[0-9]+_uxTravelBugList\" class=\"tblist\" data-tbcount=\"([0-9]+)\" data-id=\"[^\"]*\"[^>]*>(.*)</a>"); /** Second group used */ - public final static Pattern PATTERN_SEARCH_TRACKABLESINSIDE = Pattern.compile("(<img src=\"[^\"]+\" alt=\"([^\"]+)\" title=\"[^\"]*\" />[^<]*)"); - public final static Pattern PATTERN_SEARCH_DIRECTION_DISTANCE = Pattern.compile("<img src=\"/images/icons/compass/([^\\.]+)\\.gif\"[^>]*>[^<]*<br />([^<]+)</span>"); - public final static Pattern PATTERN_SEARCH_DIFFICULTY_TERRAIN = Pattern.compile("<span class=\"small\">([0-5]([\\.,]5)?)/([0-5]([\\.,]5)?)</span><br />"); - public final static Pattern PATTERN_SEARCH_CONTAINER = Pattern.compile("<img src=\"/images/icons/container/([^\\.]+)\\.gif\""); - public final static Pattern PATTERN_SEARCH_GEOCODE = Pattern.compile("\\|\\W*(GC[0-9A-Z]+)[^\\|]*\\|"); - public final static Pattern PATTERN_SEARCH_ID = Pattern.compile("name=\"CID\"[^v]*value=\"(\\d+)\""); - public final static Pattern PATTERN_SEARCH_FAVORITE = Pattern.compile("favorite-rank\">([0-9,.]+)</span>"); - public final static Pattern PATTERN_SEARCH_TOTALCOUNT = Pattern.compile("<span>Total Records\\D*(\\d+)<"); - public final static Pattern PATTERN_SEARCH_RECAPTCHA = Pattern.compile("<script[^>]*src=\"[^\"]*/recaptcha/api/challenge\\?k=([^\"]+)\"[^>]*>"); + final static Pattern PATTERN_SEARCH_TRACKABLESINSIDE = Pattern.compile("(<img src=\"[^\"]+\" alt=\"([^\"]+)\" title=\"[^\"]*\" />[^<]*)"); + final static Pattern PATTERN_SEARCH_DIRECTION_DISTANCE = Pattern.compile("<img src=\"/images/icons/compass/([^\\.]+)\\.gif\"[^>]*>[^<]*<br />([^<]+)</span>"); + final static Pattern PATTERN_SEARCH_DIFFICULTY_TERRAIN = Pattern.compile("<span class=\"small\">([0-5]([\\.,]5)?)/([0-5]([\\.,]5)?)</span><br />"); + final static Pattern PATTERN_SEARCH_CONTAINER = Pattern.compile("<img src=\"/images/icons/container/([^\\.]+)\\.gif\""); + final static Pattern PATTERN_SEARCH_GEOCODE = Pattern.compile("\\|\\W*(GC[0-9A-Z]+)[^\\|]*\\|"); + final static Pattern PATTERN_SEARCH_ID = Pattern.compile("name=\"CID\"[^v]*value=\"(\\d+)\""); + final static Pattern PATTERN_SEARCH_FAVORITE = Pattern.compile("favorite-rank\">([0-9,.]+)</span>"); + final static Pattern PATTERN_SEARCH_TOTALCOUNT = Pattern.compile("<span>Total Records\\D*(\\d+)<"); + final static Pattern PATTERN_SEARCH_RECAPTCHA = Pattern.compile("<script[^>]*src=\"[^\"]*/recaptcha/api/challenge\\?k=([^\"]+)\"[^>]*>"); public final static Pattern PATTERN_SEARCH_RECAPTCHACHALLENGE = Pattern.compile("challenge : '([^']+)'"); - public final static Pattern PATTERN_SEARCH_HIDDEN_DATE = Pattern.compile("<td style=\"width:70px\">[^<]+<span class=\"small\">([^<]+)</span>"); + final static Pattern PATTERN_SEARCH_HIDDEN_DATE = Pattern.compile("<td style=\"width:70px\">[^<]+<span class=\"small\">([^<]+)</span>"); + final static Pattern PATTERN_SEARCH_POST_ACTION = Pattern.compile("<form name=\"aspnetForm\" method=\"post\" action=\"(.*)\" id=\"aspnetForm\""); /** * Patterns for waypoints */ - public final static Pattern PATTERN_WPTYPE = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg"); - public final static Pattern PATTERN_WPPREFIXORLOOKUPORLATLON = Pattern.compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>"); - public final static Pattern PATTERN_WPNAME = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>"); - public final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)" + Pattern.quote("</td>"), Pattern.DOTALL); + final static Pattern PATTERN_WPTYPE = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg"); + final static Pattern PATTERN_WPPREFIXORLOOKUPORLATLON = Pattern.compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>"); + final static Pattern PATTERN_WPNAME = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>"); + final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)" + Pattern.quote("</td>"), Pattern.DOTALL); /** * Patterns for different purposes */ /** replace line break and paragraph tags */ - public final static Pattern PATTERN_LINEBREAK = Pattern.compile("<(br|p)[^>]*>"); - public final static Pattern PATTERN_TYPEBOX = Pattern.compile("<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$ddLogType\" id=\"ctl00_ContentBody_LogBookPanel1_ddLogType\"[^>]*>" + final static Pattern PATTERN_LINEBREAK = Pattern.compile("<(br|p)[^>]*>"); + final static Pattern PATTERN_TYPEBOX = Pattern.compile("<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$ddLogType\" id=\"ctl00_ContentBody_LogBookPanel1_ddLogType\"[^>]*>" + "(([^<]*<option[^>]*>[^<]+</option>)+)[^<]*</select>", Pattern.CASE_INSENSITIVE); - public final static Pattern PATTERN_TYPE2 = Pattern.compile("<option( selected=\"selected\")? value=\"(\\d+)\">[^<]+</option>", Pattern.CASE_INSENSITIVE); + final static Pattern PATTERN_TYPE2 = Pattern.compile("<option( selected=\"selected\")? value=\"(\\d+)\">[^<]+</option>", Pattern.CASE_INSENSITIVE); // FIXME: pattern is over specified - public final static Pattern PATTERN_TRACKABLE = Pattern.compile("<tr id=\"ctl00_ContentBody_LogBookPanel1_uxTrackables_repTravelBugs_ctl[0-9]+_row\"[^>]*>" + final static Pattern PATTERN_TRACKABLE = Pattern.compile("<tr id=\"ctl00_ContentBody_LogBookPanel1_uxTrackables_repTravelBugs_ctl[0-9]+_row\"[^>]*>" + "[^<]*<td>[^<]*<a href=\"[^\"]+\">([A-Z0-9]+)</a>[^<]*</td>[^<]*<td>([^<]+)</td>[^<]*<td>" + "[^<]*<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$uxTrackables\\$repTravelBugs\\$ctl([0-9]+)\\$ddlAction\"[^>]*>" + "([^<]*<option value=\"([0-9]+)(_[a-z]+)?\">[^<]+</option>)+" + "[^<]*</select>[^<]*</td>[^<]*</tr>", Pattern.CASE_INSENSITIVE); - public final static Pattern PATTERN_MAINTENANCE = Pattern.compile("<span id=\"ctl00_ContentBody_LogBookPanel1_lbConfirm\"[^>]*>([^<]*<font[^>]*>)?([^<]+)(</font>[^<]*)?</span>", Pattern.CASE_INSENSITIVE); - public final static Pattern PATTERN_OK1 = Pattern.compile("<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_lbHeading\"[^>]*>[^<]*</span>[^<]*</h2>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - public final static Pattern PATTERN_OK2 = Pattern.compile("<div id=[\"|']ctl00_ContentBody_LogBookPanel1_ViewLogPanel[\"|']>", Pattern.CASE_INSENSITIVE); - public final static Pattern PATTERN_IMAGE_UPLOAD_URL = Pattern.compile("title=\"Click for Larger Image\"\\s*src=\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - public final static Pattern PATTERN_VIEWSTATEFIELDCOUNT = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - public final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - public final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'"); - public final static Pattern PATTERN_LIST_PQ = Pattern.compile(Pattern.quote("(") + "(\\d+)" + Pattern.quote(")") + ".+?guid=(.+?)\".*?title=\"(.+?)\""); + final static Pattern PATTERN_MAINTENANCE = Pattern.compile("<span id=\"ctl00_ContentBody_LogBookPanel1_lbConfirm\"[^>]*>([^<]*<font[^>]*>)?([^<]+)(</font>[^<]*)?</span>", Pattern.CASE_INSENSITIVE); + final static Pattern PATTERN_OK1 = Pattern.compile("<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_lbHeading\"[^>]*>[^<]*</span>[^<]*</h2>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + final static Pattern PATTERN_OK2 = Pattern.compile("<div id=[\"|']ctl00_ContentBody_LogBookPanel1_ViewLogPanel[\"|']>", Pattern.CASE_INSENSITIVE); + final static Pattern PATTERN_IMAGE_UPLOAD_URL = Pattern.compile("title=\"Click for Larger Image\"\\s*src=\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + final static Pattern PATTERN_VIEWSTATEFIELDCOUNT = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'"); + final static Pattern PATTERN_LIST_PQ = Pattern.compile(Pattern.quote("(") + "(\\d+)" + Pattern.quote(")") + ".+?guid=(.+?)\".*?title=\"(.+?)\""); /** Live Map since 14.02.2012 */ - public final static Pattern PATTERN_USERSESSION = Pattern.compile("UserSession\\('([^']+)'"); - public final static Pattern PATTERN_SESSIONTOKEN = Pattern.compile("sessionToken:'([^']+)'"); + final static Pattern PATTERN_USERSESSION = Pattern.compile("UserSession\\('([^']+)'"); + final static Pattern PATTERN_SESSIONTOKEN = Pattern.compile("sessionToken:'([^']+)'"); - public final static Pattern PATTERN_LOG_IMAGE_UPLOAD = Pattern.compile("/seek/upload\\.aspx\\?LID=(\\d+)", Pattern.CASE_INSENSITIVE); + static final Pattern PATTERN_LOG_GUID = Pattern.compile("<a id=\"ctl00_ContentBody_LogBookPanel1_WaypointLink\"[^>]* href=\"https?://www\\.geocaching\\.com/seek/cache_details\\.aspx\\?guid=([0-9a-f-]+)\""); + final static Pattern PATTERN_LOG_IMAGE_UPLOAD = Pattern.compile("/seek/upload\\.aspx\\?LID=(\\d+)", Pattern.CASE_INSENSITIVE); - public final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only."; - public final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only."; - public final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published"; - public final static String STRING_UNPUBLISHED_FROM_SEARCH = "class=\"UnpublishedCacheSearchWidget"; // do not include closing brace as the CSS can contain additional styles - public final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred"; - public final static String STRING_DISABLED = "<li>This cache is temporarily unavailable."; - public final static String STRING_ARCHIVED = "<li>This cache has been archived,"; - public final static String STRING_CACHEDETAILS = "id=\"cacheDetails\""; + final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only."; + final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only."; + final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published"; + final static String STRING_UNPUBLISHED_FROM_SEARCH = "class=\"UnpublishedCacheSearchWidget"; // do not include closing brace as the CSS can contain additional styles + final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred"; + final static String STRING_DISABLED = "<li>This cache is temporarily unavailable."; + final static String STRING_ARCHIVED = "<li>This cache has been archived,"; + final static String STRING_CACHEDETAILS = "id=\"cacheDetails\""; /** Number of logs to retrieve from GC.com */ - public final static int NUMBER_OF_LOGS = 35; + final static int NUMBER_OF_LOGS = 35; /** Maximum number of chars for personal note. **/ public final static int PERSONAL_NOTE_MAX_CHARS = 500; diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java index bf021b9..bdea155 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java @@ -1,5 +1,6 @@ package cgeo.geocaching.connector.gc; +import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.R; @@ -14,9 +15,11 @@ import cgeo.geocaching.loaders.UrlLoader; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.TextUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import android.net.Uri; @@ -28,24 +31,24 @@ import java.util.Calendar; import java.util.Collections; import java.util.List; -public class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.LoaderCallbacks<String> { +class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.LoaderCallbacks<String> { private final LogCacheActivity activity; private final Geocache cache; private String[] viewstates; - private List<TrackableLog> trackables; + @NonNull private List<TrackableLog> trackables = Collections.emptyList(); private List<LogType> possibleLogTypes; private boolean hasLoaderError = true; - public GCLoggingManager(final LogCacheActivity activity, final Geocache cache) { + GCLoggingManager(final LogCacheActivity activity, final Geocache cache) { this.activity = activity; this.cache = cache; } @Nullable @Override - public Loader<String> onCreateLoader(int arg0, Bundle arg1) { + public Loader<String> onCreateLoader(final int arg0, final Bundle arg1) { if (!Settings.isLogin()) { // allow offline logging ActivityMixin.showToast(activity, activity.getResources().getString(R.string.err_login)); return null; @@ -54,15 +57,24 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } @Override - public void onLoadFinished(Loader<String> arg0, String page) { - + public void onLoadFinished(final Loader<String> arg0, final String page) { if (page == null) { hasLoaderError = true; } else { - viewstates = GCLogin.getViewstates(page); trackables = GCParser.parseTrackableLog(page); possibleLogTypes = GCParser.parseTypes(page); + if (StringUtils.isBlank(cache.getGuid())) { + // Acquire the cache GUID from the log page. This will not only complete the information in the database, + // but also allow the user to post a rating using GCVote since it requires the GUID to do so. + final String guid = TextUtils.getMatch(page, GCConstants.PATTERN_LOG_GUID, null); + if (StringUtils.isNotBlank(guid)) { + cache.setGuid(guid); + DataStore.saveChangedCache(cache); + } else { + Log.w("Could not acquire GUID from log page for " + cache.getGeocode()); + } + } hasLoaderError = possibleLogTypes.isEmpty(); } @@ -71,7 +83,7 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } @Override - public void onLoaderReset(Loader<String> arg0) { + public void onLoaderReset(final Loader<String> arg0) { // nothing to do } @@ -81,7 +93,8 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } @Override - public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) { + @NonNull + public LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) { try { final ImmutablePair<StatusCode, String> postResult = GCParser.postLog(cache.getGeocode(), cache.getCacheId(), viewstates, logType, @@ -96,7 +109,7 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } } return new LogResult(postResult.left, postResult.right); - } catch (Exception e) { + } catch (final Exception e) { Log.e("GCLoggingManager.postLog", e); } @@ -104,11 +117,12 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } @Override - public ImageResult postLogImage(String logId, String imageCaption, String imageDescription, Uri imageUri) { + @NonNull + public ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) { if (StringUtils.isNotBlank(imageUri.getPath())) { - ImmutablePair<StatusCode, String> imageResult = GCParser.uploadLogImage(logId, imageCaption, imageDescription, imageUri); + final ImmutablePair<StatusCode, String> imageResult = GCParser.uploadLogImage(logId, imageCaption, imageDescription, imageUri); return new ImageResult(imageResult.left, imageResult.right); } @@ -122,6 +136,7 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } @Override + @NonNull public List<TrackableLog> getTrackables() { if (hasLoaderError) { return Collections.emptyList(); @@ -130,6 +145,7 @@ public class GCLoggingManager extends AbstractLoggingManager implements LoaderMa } @Override + @NonNull public List<LogType> getPossibleLogTypes() { if (hasLoaderError) { return Collections.emptyList(); diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java index 9f430c0..16de511 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCLogin.java +++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java @@ -11,6 +11,7 @@ import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; +import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.TextUtils; import ch.boye.httpclientandroidlib.HttpResponse; @@ -22,47 +23,22 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import rx.Observable; +import rx.functions.Action0; import android.graphics.drawable.Drawable; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Collections; import java.util.Date; -import java.util.HashMap; +import java.util.GregorianCalendar; import java.util.Locale; -import java.util.Map; +import java.util.regex.Matcher; public class GCLogin extends AbstractLogin { - private static final String DEFAULT_CUSTOM_DATE_FORMAT = "MM/dd/yyyy"; + private final static String ENGLISH = "<a href=\"#\">English</a>"; - private final static String ENGLISH = "<a href=\"#\">English ▼</a>"; - - private final static Map<String, SimpleDateFormat> GC_CUSTOM_DATE_FORMATS; - public static final String LANGUAGE_CHANGE_URI = "http://www.geocaching.com/my/souvenirs.aspx"; - - static { - final String[] formats = new String[] { - DEFAULT_CUSTOM_DATE_FORMAT, - "yyyy-MM-dd", - "yyyy/MM/dd", - "dd.MM.yyyy", - "dd/MMM/yyyy", - "dd.MMM.yyyy", - "MMM/dd/yyyy", - "dd MMM yy", - "dd/MM/yyyy" - }; - - final Map<String, SimpleDateFormat> map = new HashMap<>(); - - for (final String format : formats) { - map.put(format, new SimpleDateFormat(format, Locale.ENGLISH)); - } - - GC_CUSTOM_DATE_FORMATS = Collections.unmodifiableMap(map); - } + private static final String LANGUAGE_CHANGE_URI = "http://www.geocaching.com/my/souvenirs.aspx"; private GCLogin() { // singleton @@ -76,8 +52,14 @@ public class GCLogin extends AbstractLogin { private static final GCLogin INSTANCE = new GCLogin(); } + private static StatusCode resetGcCustomDate(final StatusCode statusCode) { + Settings.setGcCustomDate(GCConstants.DEFAULT_GC_DATE); + return statusCode; + } + @Override - protected StatusCode login(boolean retry) { + @NonNull + protected StatusCode login(final boolean retry) { final ImmutablePair<String, String> credentials = Settings.getGcCredentials(); final String username = credentials.left; final String password = credentials.right; @@ -85,7 +67,7 @@ public class GCLogin extends AbstractLogin { if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { clearLoginInfo(); Log.e("Login.login: No login information stored"); - return StatusCode.NO_LOGIN_INFO_STORED; + return resetGcCustomDate(StatusCode.NO_LOGIN_INFO_STORED); } setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_working)); @@ -105,6 +87,9 @@ public class GCLogin extends AbstractLogin { if (switchToEnglish(loginData) && retry) { return login(false); } + setHomeLocation(); + refreshMemberStatus(); + detectGcCustomDate(); return StatusCode.NO_ERROR; // logged in } @@ -141,17 +126,20 @@ public class GCLogin extends AbstractLogin { } Log.i("Successfully logged in Geocaching.com as " + username + " (" + Settings.getGCMemberStatus() + ')'); Settings.setCookieStore(Cookies.dumpCookieStore()); + setHomeLocation(); + refreshMemberStatus(); + detectGcCustomDate(); return StatusCode.NO_ERROR; // logged in } - if (loginData.contains("Your username/password combination does not match.")) { + if (loginData.contains("your username or password is incorrect")) { Log.i("Failed to log in Geocaching.com as " + username + " because of wrong username/password"); - return StatusCode.WRONG_LOGIN_DATA; // wrong login + return resetGcCustomDate(StatusCode.WRONG_LOGIN_DATA); // wrong login } if (loginData.contains("You must validate your account before you can log in.")) { Log.i("Failed to log in Geocaching.com as " + username + " because account needs to be validated first"); - return StatusCode.UNVALIDATED_ACCOUNT; + return resetGcCustomDate(StatusCode.UNVALIDATED_ACCOUNT); } Log.i("Failed to log in Geocaching.com as " + username + " for some unknown reason"); @@ -160,7 +148,7 @@ public class GCLogin extends AbstractLogin { return login(false); } - return StatusCode.UNKNOWN_ERROR; // can't login + return resetGcCustomDate(StatusCode.UNKNOWN_ERROR); // can't login } public StatusCode logout() { @@ -175,14 +163,16 @@ public class GCLogin extends AbstractLogin { return StatusCode.NO_ERROR; } + private static String removeDotAndComma(final String str) { + return StringUtils.replaceChars(str, ".,", null); + } /** * Check if the user has been logged in when he retrieved the data. * - * @param page * @return <code>true</code> if user is logged in, <code>false</code> otherwise */ - public boolean getLoginStatus(@Nullable final String page) { + boolean getLoginStatus(@Nullable final String page) { if (StringUtils.isBlank(page)) { Log.e("Login.checkLogin: No page given"); return false; @@ -201,15 +191,11 @@ public class GCLogin extends AbstractLogin { setActualUserName(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); int cachesCount = 0; try { - cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); + cachesCount = Integer.parseInt(removeDotAndComma(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0"))); } catch (final NumberFormatException e) { Log.e("getLoginStatus: bad cache count", e); } setActualCachesFound(cachesCount); - Settings.setGCMemberStatus(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null)); - if (page.contains(GCConstants.MEMBER_STATUS_RENEW)) { - Settings.setGCMemberStatus(GCConstants.MEMBER_STATUS_PM); - } return true; } @@ -231,7 +217,7 @@ public class GCLogin extends AbstractLogin { * @param previousPage the content of the last loaded page * @return <code>true</code> if a switch was necessary and succesfully performed (non-English -> English) */ - private boolean switchToEnglish(String previousPage) { + private boolean switchToEnglish(final String previousPage) { if (previousPage != null && previousPage.contains(ENGLISH)) { Log.i("Geocaching.com language already set to English"); // get find count @@ -256,21 +242,16 @@ public class GCLogin extends AbstractLogin { return false; } - public Observable<Drawable> downloadAvatarAndGetMemberStatus() { + public Observable<Drawable> downloadAvatar() { try { final String responseData = StringUtils.defaultString(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/"))); final String profile = TextUtils.replaceWhitespace(responseData); - Settings.setGCMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null)); - if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) { - Settings.setGCMemberStatus(GCConstants.MEMBER_STATUS_PM); - } - - setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""))); + setActualCachesFound(Integer.parseInt(removeDotAndComma(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1")))); final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null); if (avatarURL != null) { - final HtmlImage imgGetter = new HtmlImage("", false, 0, false); + final HtmlImage imgGetter = new HtmlImage(HtmlImage.SHARED, false, 0, false); return imgGetter.fetchDrawable(avatarURL.replace("avatar", "user/large")).cast(Drawable.class); } // No match? There may be no avatar set by user. @@ -281,12 +262,47 @@ public class GCLogin extends AbstractLogin { return null; } + @Nullable + static String retrieveHomeLocation() { + final String result = Network.getResponseData(Network.getRequest("https://www.geocaching.com/account/settings/homelocation")); + return TextUtils.getMatch(result, GCConstants.PATTERN_HOME_LOCATION, null); + } + + private static void setHomeLocation() { + RxUtils.networkScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final String homeLocationStr = retrieveHomeLocation(); + if (StringUtils.isNotBlank(homeLocationStr) && !StringUtils.equals(homeLocationStr, Settings.getHomeLocation())) { + assert homeLocationStr != null; + Log.i("Setting home location to " + homeLocationStr); + Settings.setHomeLocation(homeLocationStr); + } + } + }); + } + + private static void refreshMemberStatus() { + RxUtils.networkScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final String page = StringUtils.defaultString(Network.getResponseData(Network.getRequest("https://www.geocaching.com/account/settings/membership"))); + final Matcher match = GCConstants.PATTERN_MEMBERSHIP.matcher(page); + if (match.find()) { + Log.d("Setting member status to " + match.group(1)); + Settings.setGCMemberStatus(match.group(1)); + } else { + Log.w("Cannot determine member status"); + } + } + }); + } + /** * Detect user date settings on geocaching.com */ - public static void detectGcCustomDate() { - - final String result = Network.getResponseData(Network.getRequest("http://www.geocaching.com/account/ManagePreferences.aspx")); + private static void detectGcCustomDate() { + final String result = Network.getResponseData(Network.getRequest("https://www.geocaching.com/account/settings/preferences")); if (null == result) { Log.w("Login.detectGcCustomDate: result is null"); @@ -300,40 +316,15 @@ public class GCLogin extends AbstractLogin { } public static Date parseGcCustomDate(final String input, final String format) throws ParseException { - if (StringUtils.isBlank(input)) { - throw new ParseException("Input is null", 0); - } - - final String trimmed = input.trim(); - - if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) { - try { - return GC_CUSTOM_DATE_FORMATS.get(format).parse(trimmed); - } catch (final ParseException e) { - } - } - - for (final SimpleDateFormat sdf : GC_CUSTOM_DATE_FORMATS.values()) { - try { - return sdf.parse(trimmed); - } catch (final ParseException e) { - } - } - - throw new ParseException("No matching pattern", 0); + return new SimpleDateFormat(format, Locale.ENGLISH).parse(input.trim()); } - public static Date parseGcCustomDate(final String input) throws ParseException { + static Date parseGcCustomDate(final String input) throws ParseException { return parseGcCustomDate(input, Settings.getGcCustomDate()); } - public static SimpleDateFormat getCustomGcDateFormat() { - final String format = Settings.getGcCustomDate(); - if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) { - return GC_CUSTOM_DATE_FORMATS.get(format); - } - - return GC_CUSTOM_DATE_FORMATS.get(DEFAULT_CUSTOM_DATE_FORMAT); + static String formatGcCustomDate(final int year, final int month, final int day) { + return new SimpleDateFormat(Settings.getGcCustomDate(), Locale.ENGLISH).format(new GregorianCalendar(year, month - 1, day).getTime()); } /** @@ -341,7 +332,7 @@ public class GCLogin extends AbstractLogin { * - Array is null * - or all elements are null or empty strings */ - public static boolean isEmpty(String[] a) { + public static boolean isEmpty(final String[] a) { if (a == null) { return true; } @@ -359,7 +350,7 @@ public class GCLogin extends AbstractLogin { * * @return String[] with all view states */ - public static String[] getViewstates(String page) { + public static String[] getViewstates(final String page) { // Get the number of viewstates. // If there is only one viewstate, __VIEWSTATEFIELDCOUNT is not present @@ -407,7 +398,7 @@ public class GCLogin extends AbstractLogin { /** * put viewstates into request parameters */ - public static void putViewstates(final Parameters params, final String[] viewstates) { + static void putViewstates(final Parameters params, final String[] viewstates) { if (ArrayUtils.isEmpty(viewstates)) { return; } @@ -424,17 +415,15 @@ public class GCLogin extends AbstractLogin { * transfers the viewstates variables from a page (response) to parameters * (next request) */ - public static void transferViewstates(final String page, final Parameters params) { + static void transferViewstates(final String page, final Parameters params) { putViewstates(params, getViewstates(page)); } /** * POST HTTP request. Do the request a second time if the user is not logged in * - * @param uri - * @return */ - public String postRequestLogged(final String uri, final Parameters params) { + String postRequestLogged(final String uri, final Parameters params) { final String data = Network.getResponseData(Network.postRequest(uri, params)); if (getLoginStatus(data)) { @@ -452,12 +441,9 @@ public class GCLogin extends AbstractLogin { /** * GET HTTP request. Do the request a second time if the user is not logged in * - * @param uri - * @param params - * @return */ @Nullable - public String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) { + String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) { final HttpResponse response = Network.getRequest(uri, params); final String data = Network.getResponseData(response, canRemoveWhitespace(uri)); @@ -478,8 +464,6 @@ public class GCLogin extends AbstractLogin { * Unfortunately the cache details page contains user generated whitespace in the personal note, therefore we cannot * remove the white space from cache details pages. * - * @param uri - * @return */ private static boolean canRemoveWhitespace(final String uri) { return !StringUtils.contains(uri, "cache_details"); @@ -490,8 +474,8 @@ public class GCLogin extends AbstractLogin { * * @return first is user session, second is session token */ - public @NonNull - MapTokens getMapTokens() { + @NonNull + public MapTokens getMapTokens() { final String data = getRequestLogged(GCConstants.URL_LIVE_MAP, null); final String userSession = TextUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, ""); final String sessionToken = TextUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, ""); diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index 27ce06e..243d84c 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -1,35 +1,40 @@ package cgeo.geocaching.connector.gc; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.SearchResult; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; -import cgeo.geocaching.enumerations.LiveMapStrategy.StrategyFlag; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter.Format; -import cgeo.geocaching.geopoint.Units; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.files.ParserException; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter.Format; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.location.Viewport; +import cgeo.geocaching.maps.LivemapStrategy; +import cgeo.geocaching.maps.LivemapStrategy.Flag; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Formatter; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import org.eclipse.jdt.annotation.NonNull; import rx.Observable; import rx.functions.Func2; import android.graphics.Bitmap; +import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; @@ -43,7 +48,7 @@ import java.util.Set; public class GCMap { private static Viewport lastSearchViewport = null; - public static SearchResult searchByGeocodes(Set<String> geocodes) { + public static SearchResult searchByGeocodes(final Set<String> geocodes) { final SearchResult result = new SearchResult(); final String geocodeList = StringUtils.join(geocodes.toArray(), "|"); @@ -60,53 +65,41 @@ public class GCMap { // {"name":"HP: Hannover - Sahlkamp","gc":"GC2Q97X","g":"a09149ca-00e0-4aa2-b332-db2b4dfb18d2","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"0","difficulty":{"text":1.0,"value":"1"},"terrain":{"text":1.5,"value":"1_5"},"hidden":"5/29/2011","container":{"text":"Small","value":"small.gif"},"type":{"text":"Traditional Cache","value":2},"owner":{"text":"GeoM@n","value":"1deaa69e-6bcc-421d-95a1-7d32b468cb82"}}] // } - final JSONObject json = new JSONObject(data); - final String status = json.getString("status"); + final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data); + final String status = json.path("status").asText(); if (StringUtils.isBlank(status)) { - - throw new JSONException("No status inside JSON"); + throw new ParserException("No status inside JSON"); } if ("success".compareTo(status) != 0) { - throw new JSONException("Wrong status inside JSON"); + throw new ParserException("Wrong status inside JSON"); } - final JSONArray dataArray = json.getJSONArray("data"); + final ArrayNode dataArray = (ArrayNode) json.get("data"); if (dataArray == null) { - throw new JSONException("No data inside JSON"); + throw new ParserException("No data inside JSON"); } final ArrayList<Geocache> caches = new ArrayList<>(); - for (int j = 0; j < dataArray.length(); j++) { + for (final JsonNode dataObject: dataArray) { final Geocache cache = new Geocache(); - - JSONObject dataObject = dataArray.getJSONObject(j); - cache.setName(dataObject.getString("name")); - cache.setGeocode(dataObject.getString("gc")); - cache.setGuid(dataObject.getString("g")); // 34c2e609-5246-4f91-9029-d6c02b0f2a82" - cache.setDisabled(!dataObject.getBoolean("available")); - cache.setArchived(dataObject.getBoolean("archived")); - cache.setPremiumMembersOnly(dataObject.getBoolean("subrOnly")); + cache.setName(dataObject.path("name").asText()); + cache.setGeocode(dataObject.path("gc").asText()); + cache.setGuid(dataObject.path("g").asText()); // 34c2e609-5246-4f91-9029-d6c02b0f2a82" + cache.setDisabled(!dataObject.path("available").asBoolean()); + cache.setArchived(dataObject.path("archived").asBoolean()); + cache.setPremiumMembersOnly(dataObject.path("subrOnly").asBoolean()); // "li" seems to be "false" always - cache.setFavoritePoints(Integer.parseInt(dataObject.getString("fp"))); - JSONObject difficultyObj = dataObject.getJSONObject("difficulty"); - cache.setDifficulty(Float.parseFloat(difficultyObj.getString("text"))); // 3.5 - JSONObject terrainObj = dataObject.getJSONObject("terrain"); - cache.setTerrain(Float.parseFloat(terrainObj.getString("text"))); // 1.5 - cache.setHidden(GCLogin.parseGcCustomDate(dataObject.getString("hidden"), "MM/dd/yyyy")); // 7/23/2001 - JSONObject containerObj = dataObject.getJSONObject("container"); - cache.setSize(CacheSize.getById(containerObj.getString("text"))); // Regular - JSONObject typeObj = dataObject.getJSONObject("type"); - cache.setType(CacheType.getByPattern(typeObj.getString("text"))); // Traditional Cache - JSONObject ownerObj = dataObject.getJSONObject("owner"); - cache.setOwnerDisplayName(ownerObj.getString("text")); + cache.setFavoritePoints(Integer.parseInt(dataObject.path("fp").asText())); + cache.setDifficulty(Float.parseFloat(dataObject.path("difficulty").path("text").asText())); // 3.5 + cache.setTerrain(Float.parseFloat(dataObject.path("terrain").path("text").asText())); // 1.5 + cache.setHidden(GCLogin.parseGcCustomDate(dataObject.path("hidden").asText(), "MM/dd/yyyy")); // 7/23/2001 + cache.setSize(CacheSize.getById(dataObject.path("container").path("text").asText())); // Regular + cache.setType(CacheType.getByPattern(dataObject.path("type").path("text").asText())); // Traditional Cache + cache.setOwnerDisplayName(dataObject.path("owner").path("text").asText()); caches.add(cache); } result.addAndPutInCache(caches); - } catch (JSONException e) { - result.setError(StatusCode.UNKNOWN_ERROR); - } catch (ParseException e) { - result.setError(StatusCode.UNKNOWN_ERROR); - } catch (NumberFormatException e) { + } catch (ParserException | ParseException | IOException | NumberFormatException ignored) { result.setError(StatusCode.UNKNOWN_ERROR); } return result; @@ -117,7 +110,7 @@ public class GCMap { * Retrieved data. * @return SearchResult. Never null. */ - public static SearchResult parseMapJSON(final String data, Tile tile, Bitmap bitmap, final Strategy strategy) { + public static SearchResult parseMapJSON(final String data, final Tile tile, final Bitmap bitmap, final LivemapStrategy strategy) { final SearchResult searchResult = new SearchResult(); try { @@ -125,7 +118,7 @@ public class GCMap { final LeastRecentlyUsedMap<String, String> nameCache = new LeastRecentlyUsedMap.LruCache<>(2000); // JSON id, cache name if (StringUtils.isEmpty(data)) { - throw new JSONException("No page given"); + throw new ParserException("No page given"); } // Example JSON information @@ -134,34 +127,33 @@ public class GCMap { // "data":{"55_55":[{"i":"gEaR","n":"Spiel & Sport"}],"55_54":[{"i":"gEaR","n":"Spiel & Sport"}],"17_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"55_53":[{"i":"gEaR","n":"Spiel & Sport"}],"17_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"17_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"57_53":[{"i":"gEaR","n":"Spiel & Sport"}],"57_55":[{"i":"gEaR","n":"Spiel & Sport"}],"3_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"3_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"57_54":[{"i":"gEaR","n":"Spiel & Sport"}],"3_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"15_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"15_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"15_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"4_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"4_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"4_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"16_25":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"16_26":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"16_27":[{"i":"Rkzt","n":"EDSSW: Rathaus "}],"2_62":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"2_60":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"2_61":[{"i":"gOWz","n":"Baumarktserie - Wer Wo Was -"}],"56_53":[{"i":"gEaR","n":"Spiel & Sport"}],"56_54":[{"i":"gEaR","n":"Spiel & Sport"}],"56_55":[{"i":"gEaR","n":"Spiel & Sport"}]} // } - final JSONObject json = new JSONObject(data); + final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data); - final JSONArray grid = json.getJSONArray("grid"); - if (grid == null || grid.length() != (UTFGrid.GRID_MAXY + 1)) { - throw new JSONException("No grid inside JSON"); + final ArrayNode grid = (ArrayNode) json.get("grid"); + if (grid == null || grid.size() != (UTFGrid.GRID_MAXY + 1)) { + throw new ParserException("No grid inside JSON"); } - final JSONArray keys = json.getJSONArray("keys"); + final ArrayNode keys = (ArrayNode) json.get("keys"); if (keys == null) { - throw new JSONException("No keys inside JSON"); + throw new ParserException("No keys inside JSON"); } - final JSONObject dataObject = json.getJSONObject("data"); + final ObjectNode dataObject = (ObjectNode) json.get("data"); if (dataObject == null) { - throw new JSONException("No data inside JSON"); + throw new ParserException("No data inside JSON"); } // iterate over the data and construct all caches in this tile - Map<String, List<UTFGridPosition>> positions = new HashMap<>(); // JSON id as key - Map<String, List<UTFGridPosition>> singlePositions = new HashMap<>(); // JSON id as key - - for (int i = 1; i < keys.length(); i++) { // index 0 is empty - String key = keys.getString(i); - if (StringUtils.isNotBlank(key)) { - UTFGridPosition pos = UTFGridPosition.fromString(key); - JSONArray dataForKey = dataObject.getJSONArray(key); - for (int j = 0; j < dataForKey.length(); j++) { - JSONObject cacheInfo = dataForKey.getJSONObject(j); - String id = cacheInfo.getString("i"); - nameCache.put(id, cacheInfo.getString("n")); + final Map<String, List<UTFGridPosition>> positions = new HashMap<>(); // JSON id as key + final Map<String, List<UTFGridPosition>> singlePositions = new HashMap<>(); // JSON id as key + + for (final JsonNode rawKey: keys) { + final String key = rawKey.asText(); + if (StringUtils.isNotBlank(key)) { // index 0 is empty + final UTFGridPosition pos = UTFGridPosition.fromString(key); + final ArrayNode dataForKey = (ArrayNode) dataObject.get(key); + for (final JsonNode cacheInfo: dataForKey) { + final String id = cacheInfo.get("i").asText(); + nameCache.put(id, cacheInfo.get("n").asText()); List<UTFGridPosition> listOfPositions = positions.get(id); List<UTFGridPosition> singleListOfPositions = singlePositions.get(id); @@ -174,7 +166,7 @@ public class GCMap { } listOfPositions.add(pos); - if (dataForKey.length() == 1) { + if (dataForKey.size() == 1) { singleListOfPositions.add(pos); } @@ -183,18 +175,18 @@ public class GCMap { } final ArrayList<Geocache> caches = new ArrayList<>(); - for (Entry<String, List<UTFGridPosition>> entry : positions.entrySet()) { - String id = entry.getKey(); - List<UTFGridPosition> pos = entry.getValue(); - UTFGridPosition xy = UTFGrid.getPositionInGrid(pos); - Geocache cache = new Geocache(); + for (final Entry<String, List<UTFGridPosition>> entry : positions.entrySet()) { + final String id = entry.getKey(); + final List<UTFGridPosition> pos = entry.getValue(); + final UTFGridPosition xy = UTFGrid.getPositionInGrid(pos); + final Geocache cache = new Geocache(); cache.setDetailed(false); cache.setReliableLatLon(false); cache.setGeocode(id); cache.setName(nameCache.get(id)); cache.setCoords(tile.getCoord(xy), tile.getZoomLevel()); - if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && bitmap != null) { - for (UTFGridPosition singlePos : singlePositions.get(id)) { + if (strategy.flags.contains(LivemapStrategy.Flag.PARSE_TILES) && bitmap != null) { + for (final UTFGridPosition singlePos : singlePositions.get(id)) { if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomLevel())) { break; // cache parsed } @@ -220,9 +212,7 @@ public class GCMap { searchResult.addAndPutInCache(caches); Log.d("Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString()); - } catch (RuntimeException e) { - Log.e("GCMap.parseMapJSON", e); - } catch (JSONException e) { + } catch (RuntimeException | ParserException | IOException e) { Log.e("GCMap.parseMapJSON", e); } @@ -236,19 +226,19 @@ public class GCMap { * Area to search * @param tokens * Live map tokens - * @return */ + @NonNull public static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens) { - int speed = (int) CgeoApplication.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h - Strategy strategy = Settings.getLiveMapStrategy(); - if (strategy == Strategy.AUTO) { - strategy = speed >= 30 ? Strategy.FAST : Strategy.DETAILED; + final int speed = (int) Sensors.getInstance().currentGeo().getSpeed() * 60 * 60 / 1000; // in km/h + LivemapStrategy strategy = Settings.getLiveMapStrategy(); + if (strategy == LivemapStrategy.AUTO) { + strategy = speed >= 30 ? LivemapStrategy.FAST : LivemapStrategy.DETAILED; } - SearchResult result = searchByViewport(viewport, tokens, strategy); + final SearchResult result = searchByViewport(viewport, tokens, strategy); if (Settings.isDebug()) { - StringBuilder text = new StringBuilder(Formatter.SEPARATOR).append(strategy.getL10n()).append(Formatter.SEPARATOR).append(Units.getSpeed(speed)); + final StringBuilder text = new StringBuilder(Formatter.SEPARATOR).append(strategy.getL10n()).append(Formatter.SEPARATOR).append(Units.getSpeed(speed)); result.setUrl(result.getUrl() + text); } @@ -266,9 +256,9 @@ public class GCMap { * Live map tokens * @param strategy * Strategy for data retrieval and parsing, @see Strategy - * @return */ - private static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens, final Strategy strategy) { + @NonNull + private static SearchResult searchByViewport(final Viewport viewport, final MapTokens tokens, final LivemapStrategy strategy) { Log.d("GCMap.searchByViewport" + viewport.toString()); final SearchResult searchResult = new SearchResult(); @@ -277,7 +267,7 @@ public class GCMap { searchResult.setUrl(viewport.getCenter().format(Format.LAT_LON_DECMINUTE)); } - if (strategy.flags.contains(StrategyFlag.LOAD_TILES)) { + if (strategy.flags.contains(LivemapStrategy.Flag.LOAD_TILES)) { final Set<Tile> tiles = Tile.getTilesForViewport(viewport); if (Settings.isDebug()) { @@ -347,11 +337,11 @@ public class GCMap { } } - if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY) && Settings.isGCPremiumMember()) { + if (strategy.flags.contains(Flag.SEARCH_NEARBY) && Settings.isGCPremiumMember()) { final Geopoint center = viewport.getCenter(); if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { //FIXME We don't have a RecaptchaReceiver!? - SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null); + final SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null); if (search != null && !search.isEmpty()) { final Set<String> geocodes = search.getGeocodes(); lastSearchViewport = DataStore.getBounds(geocodes); @@ -365,11 +355,10 @@ public class GCMap { /** * Creates a list of caches types to filter on the live map (exclusion string) - * + * * @param typeToDisplay * - cache type to omit from exclusion list so it gets displayed - * @return - * + * * cache types for live map filter: * 2 = traditional, 9 = ape, 5 = letterbox * 3 = multi @@ -377,8 +366,8 @@ public class GCMap { * 4 = virtual, 11 = webcam, 137 = earth * 8 = mystery, 1858 = whereigo */ - private static String getCacheTypeFilter(CacheType typeToDisplay) { - Set<String> filterTypes = new HashSet<>(); + private static String getCacheTypeFilter(final CacheType typeToDisplay) { + final Set<String> filterTypes = new HashSet<>(); // Put all types in set, remove what should be visible in a second step filterTypes.addAll(Arrays.asList("2", "9", "5", "3", "6", "453", "13", "1304", "4", "11", "137", "8", "1858")); switch (typeToDisplay) { diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index c771049..7fef8b4 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -22,14 +22,15 @@ import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.files.LocParser; import cgeo.geocaching.gcvote.GCVote; import cgeo.geocaching.gcvote.GCVoteRating; -import cgeo.geocaching.geopoint.DistanceParser; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.DistanceParser; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; -import cgeo.geocaching.ui.DirectionImage; import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.HtmlUtils; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; import cgeo.geocaching.utils.RxUtils; @@ -38,15 +39,16 @@ import cgeo.geocaching.utils.TextUtils; import ch.boye.httpclientandroidlib.HttpResponse; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import rx.Observable; import rx.Observable.OnSubscribe; @@ -54,11 +56,15 @@ import rx.Subscriber; import rx.functions.Action1; import rx.functions.Func0; import rx.functions.Func2; +import rx.schedulers.Schedulers; import android.net.Uri; import android.text.Html; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.text.Collator; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -66,16 +72,22 @@ import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.EnumSet; -import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.regex.Pattern; public abstract class GCParser { - private final static SynchronizedDateFormat dateTbIn1 = new SynchronizedDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009 - private final static SynchronizedDateFormat dateTbIn2 = new SynchronizedDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009 + @NonNull + private final static SynchronizedDateFormat DATE_TB_IN_1 = new SynchronizedDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009 + + @NonNull + private final static SynchronizedDateFormat DATE_TB_IN_2 = new SynchronizedDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009 + @NonNull + private final static ImmutablePair<StatusCode, Geocache> UNKNOWN_PARSE_ERROR = ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null); + + @Nullable private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(pageContent)) { Log.e("GCParser.parseSearch: No page given"); @@ -125,12 +137,12 @@ public abstract class GCParser { page = page.substring(startPos + 1, endPos - startPos + 1); // cut between <table> and </table> - final String[] rows = page.split("<tr class="); - final int rows_count = rows.length; + final String[] rows = StringUtils.splitByWholeSeparator(page, "<tr class="); + final int rowsCount = rows.length; int excludedCaches = 0; final ArrayList<Geocache> caches = new ArrayList<>(); - for (int z = 1; z < rows_count; z++) { + for (int z = 1; z < rowsCount; z++) { final Geocache cache = new Geocache(); final String row = rows[z]; @@ -161,7 +173,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse GUID and/or Disabled - Log.w("GCParser.parseSearch: Failed to parse GUID and/or Disabled data"); + Log.w("GCParser.parseSearch: Failed to parse GUID and/or Disabled data", e); } if (Settings.isExcludeDisabledCaches() && (cache.isDisabled() || cache.isArchived())) { @@ -173,11 +185,11 @@ public abstract class GCParser { cache.setGeocode(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true)); // cache type - cache.setType(CacheType.getByPattern(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true))); + cache.setType(CacheType.getByPattern(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, null))); // cache direction - image if (Settings.getLoadDirImg()) { - final String direction = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 1, null, false); + final String direction = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, null); if (direction != null) { cache.setDirectionImg(direction); } @@ -187,7 +199,7 @@ public abstract class GCParser { final String distance = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 2, null, false); if (distance != null) { cache.setDistance(DistanceParser.parseDistance(distance, - !Settings.isUseImperialUnits())); + !Settings.useImperialUnits())); } // difficulty/terrain @@ -204,19 +216,19 @@ public abstract class GCParser { } // size - final String container = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, 1, null, false); + final String container = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, null); cache.setSize(CacheSize.getById(container)); // date hidden, makes sorting event caches easier - final String dateHidden = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_HIDDEN_DATE, false, 1, null, false); + final String dateHidden = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_HIDDEN_DATE, false, null); if (StringUtils.isNotBlank(dateHidden)) { try { - Date date = GCLogin.parseGcCustomDate(dateHidden); + final Date date = GCLogin.parseGcCustomDate(dateHidden); if (date != null) { cache.setHidden(date); } - } catch (ParseException e) { - Log.e("Error parsing event date from search"); + } catch (final ParseException e) { + Log.e("Error parsing event date from search", e); } } @@ -235,6 +247,7 @@ public abstract class GCParser { } if (StringUtils.isNotBlank(inventoryPre)) { + assert inventoryPre != null; final MatcherWrapper matcherTbsInside = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE, inventoryPre); while (matcherTbsInside.find()) { if (matcherTbsInside.groupCount() == 2 && @@ -266,7 +279,7 @@ public abstract class GCParser { cache.setFavoritePoints(Integer.parseInt(result)); } } catch (final NumberFormatException e) { - Log.w("GCParser.parseSearch: Failed to parse favorite count"); + Log.w("GCParser.parseSearch: Failed to parse favorite count", e); } caches.add(cache); @@ -280,7 +293,7 @@ public abstract class GCParser { searchResult.setTotalCountGC(Integer.parseInt(result) - excludedCaches); } } catch (final NumberFormatException e) { - Log.w("GCParser.parseSearch: Failed to parse cache count"); + Log.w("GCParser.parseSearch: Failed to parse cache count", e); } String recaptchaText = null; @@ -291,6 +304,13 @@ public abstract class GCParser { if (!cids.isEmpty() && (Settings.isGCPremiumMember() || showCaptcha) && ((recaptchaReceiver == null || StringUtils.isBlank(recaptchaReceiver.getChallenge())) || StringUtils.isNotBlank(recaptchaText))) { Log.i("Trying to get .loc for " + cids.size() + " caches"); + final Observable<Set<Geocache>> storedCaches = Observable.defer(new Func0<Observable<Set<Geocache>>>() { + @Override + public Observable<Set<Geocache>> call() { + return Observable.just(DataStore.loadCaches(Geocache.getGeocodes(caches), LoadFlags.LOAD_CACHE_OR_DB)); + } + }).subscribeOn(Schedulers.io()).cache(); + storedCaches.subscribe(); // Force asynchronous start of database loading try { // get coordinates for parsed caches @@ -306,41 +326,41 @@ public abstract class GCParser { params.put("recaptcha_challenge_field", recaptchaReceiver.getChallenge()); params.put("recaptcha_response_field", recaptchaText); } - params.put("ctl00$ContentBody$uxDownloadLoc", "Download Waypoints"); + params.put("Download", "Download Waypoints"); - final String coordinates = Network.getResponseData(Network.postRequest("http://www.geocaching.com/seek/nearest.aspx", params), false); + // retrieve target url + final String queryUrl = TextUtils.getMatch(pageContent, GCConstants.PATTERN_SEARCH_POST_ACTION, ""); - if (StringUtils.contains(coordinates, "You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) { - Log.i("User has not agreed to the license agreement. Can\'t download .loc file."); - searchResult.setError(StatusCode.UNAPPROVED_LICENSE); - return searchResult; - } + if (StringUtils.isEmpty(queryUrl)) { + Log.w("Loc download url not found"); + } else { - LocParser.parseLoc(searchResult, coordinates); + final String coordinates = Network.getResponseData(Network.postRequest("http://www.geocaching.com/seek/" + queryUrl, params), false); - } catch (final RuntimeException e) { - Log.e("GCParser.parseSearch.CIDs", e); - } - } + if (StringUtils.contains(coordinates, "You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com")) { + Log.i("User has not agreed to the license agreement. Can\'t download .loc file."); + searchResult.setError(StatusCode.UNAPPROVED_LICENSE); + return searchResult; + } - // get direction images - if (Settings.getLoadDirImg()) { - final Set<Geocache> cachesReloaded = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); - for (final Geocache cache : cachesReloaded) { - if (cache.getCoords() == null && StringUtils.isNotEmpty(cache.getDirectionImg())) { - DirectionImage.getDrawable(cache.getDirectionImg()); + LocParser.parseLoc(searchResult, coordinates, storedCaches.toBlocking().single()); } + + } catch (final RuntimeException e) { + Log.e("GCParser.parseSearch.CIDs", e); } } return searchResult; } + @Nullable private static Float parseStars(final String value) { final float floatValue = Float.parseFloat(StringUtils.replaceChars(value, ',', '.')); return floatValue >= 0.5 && floatValue <= 5.0 ? floatValue : null; } + @Nullable static SearchResult parseCache(final String page, final CancellableHandler handler) { final ImmutablePair<StatusCode, Geocache> parsed = parseCacheFromText(page, handler); // attention: parseCacheFromText already stores implicitly through searchResult.addCache @@ -366,12 +386,13 @@ public abstract class GCParser { return new SearchResult(cache); } + @NonNull static SearchResult parseAndSaveCacheFromText(final String page, @Nullable final CancellableHandler handler) { final ImmutablePair<StatusCode, Geocache> parsed = parseCacheFromText(page, handler); final SearchResult result = new SearchResult(parsed.left); if (parsed.left == StatusCode.NO_ERROR) { result.addAndPutInCache(Collections.singletonList(parsed.right)); - DataStore.saveLogsWithoutTransaction(parsed.right.getGeocode(), getLogs(page, Logs.ALL).toBlocking().toIterable()); + DataStore.saveLogs(parsed.right.getGeocode(), getLogs(parseUserToken(page), Logs.ALL).toBlocking().toIterable()); } return result; } @@ -380,17 +401,20 @@ public abstract class GCParser { * Parse cache from text and return either an error code or a cache object in a pair. Note that inline logs are * not parsed nor saved, while the cache itself is. * - * @param pageIn the page text to parse - * @param handler the handler to send the progress notifications to - * @return a pair, with a {@link StatusCode} on the left, and a non-nulll cache objet on the right - * iff the status code is {@link StatusCode.NO_ERROR}. + * @param pageIn + * the page text to parse + * @param handler + * the handler to send the progress notifications to + * @return a pair, with a {@link StatusCode} on the left, and a non-null cache object on the right + * iff the status code is {@link cgeo.geocaching.enumerations.StatusCode#NO_ERROR}. */ + @NonNull static private ImmutablePair<StatusCode, Geocache> parseCacheFromText(final String pageIn, @Nullable final CancellableHandler handler) { CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); if (StringUtils.isBlank(pageIn)) { Log.e("GCParser.parseCache: No page given"); - return null; + return UNKNOWN_PARSE_ERROR; } if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) { @@ -403,12 +427,12 @@ public abstract class GCParser { final String cacheName = Html.fromHtml(TextUtils.getMatch(pageIn, GCConstants.PATTERN_NAME, true, "")).toString(); if (GCConstants.STRING_UNKNOWN_ERROR.equalsIgnoreCase(cacheName)) { - return ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null); + return UNKNOWN_PARSE_ERROR; } // first handle the content with line breaks, then trim everything for easier matching and reduced memory consumption in parsed fields String personalNoteWithLineBreaks = ""; - MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn); + final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn); if (matcher.find()) { personalNoteWithLineBreaks = matcher.group(1).trim(); } @@ -446,7 +470,7 @@ public abstract class GCParser { final int pos = tableInside.indexOf(GCConstants.STRING_CACHEDETAILS); if (pos == -1) { Log.e("GCParser.parseCache: ID \"cacheDetails\" not found on page"); - return null; + return UNKNOWN_PARSE_ERROR; } tableInside = tableInside.substring(pos); @@ -490,7 +514,7 @@ public abstract class GCParser { } } catch (final ParseException e) { // failed to parse cache hidden date - Log.w("GCParser.parseCache: Failed to parse cache hidden (event) date"); + Log.w("GCParser.parseCache: Failed to parse cache hidden (event) date", e); } // favorite @@ -547,17 +571,17 @@ public abstract class GCParser { final String longDescription = TextUtils.getMatch(page, GCConstants.PATTERN_DESC, true, ""); String relatedWebPage = TextUtils.getMatch(page, GCConstants.PATTERN_RELATED_WEB_PAGE, true, ""); if (StringUtils.isNotEmpty(relatedWebPage)) { - relatedWebPage = String.format("<a href=\"%s\"><b>%s</b></a><br/><br/>", relatedWebPage, relatedWebPage); + relatedWebPage = String.format("<br/><br/><a href=\"%s\"><b>%s</b></a>", relatedWebPage, relatedWebPage); } - cache.setDescription(relatedWebPage + longDescription); + cache.setDescription(longDescription + relatedWebPage); // cache attributes try { + final ArrayList<String> attributes = new ArrayList<>(); final String attributesPre = TextUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null); - if (null != attributesPre) { + if (attributesPre != null) { final MatcherWrapper matcherAttributesInside = new MatcherWrapper(GCConstants.PATTERN_ATTRIBUTESINSIDE, attributesPre); - final ArrayList<String> attributes = new ArrayList<>(); while (matcherAttributesInside.find()) { if (matcherAttributesInside.groupCount() > 1 && !matcherAttributesInside.group(2).equalsIgnoreCase("blank")) { // by default, use the tooltip of the attribute @@ -575,17 +599,17 @@ public abstract class GCParser { attributes.add(attribute); } } - cache.setAttributes(attributes); } + cache.setAttributes(attributes); } catch (final RuntimeException e) { // failed to parse cache attributes - Log.w("GCParser.parseCache: Failed to parse cache attributes"); + Log.w("GCParser.parseCache: Failed to parse cache attributes", e); } // cache spoilers try { if (CancellableHandler.isCancelled(handler)) { - return null; + return UNKNOWN_PARSE_ERROR; } CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); @@ -608,7 +632,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse cache spoilers - Log.w("GCParser.parseCache: Failed to parse cache spoilers"); + Log.w("GCParser.parseCache: Failed to parse cache spoilers", e); } // cache inventory @@ -642,7 +666,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse cache inventory - Log.w("GCParser.parseCache: Failed to parse cache inventory (2)"); + Log.w("GCParser.parseCache: Failed to parse cache inventory (2)", e); } // cache logs counts @@ -664,7 +688,7 @@ public abstract class GCParser { } } catch (final NumberFormatException e) { // failed to parse logs - Log.w("GCParser.parseCache: Failed to parse cache log count"); + Log.w("GCParser.parseCache: Failed to parse cache log count", e); } // waypoints - reset collection @@ -680,13 +704,13 @@ public abstract class GCParser { cache.addOrChangeWaypoint(waypoint, false); cache.setUserModifiedCoords(true); } - } catch (final Geopoint.GeopointException e) { + } catch (final Geopoint.GeopointException ignored) { } int wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">"); if (wpBegin != -1) { // parse waypoints if (CancellableHandler.isCancelled(handler)) { - return null; + return UNKNOWN_PARSE_ERROR; } CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints); @@ -707,10 +731,15 @@ public abstract class GCParser { wpList = wpList.substring(wpBegin + 7, wpEnd); } - final String[] wpItems = wpList.split("<tr"); + final String[] wpItems = StringUtils.splitByWholeSeparator(wpList, "<tr"); - for (int j = 1; j < wpItems.length; j++) { - String[] wp = wpItems[j].split("<td"); + for (int j = 1; j < wpItems.length; j += 2) { + final String[] wp = StringUtils.splitByWholeSeparator(wpItems[j], "<td"); + assert wp != null; + if (wp.length < 8) { + Log.e("GCParser.cacheParseFromText: not enough waypoint columns in table"); + continue; + } // waypoint name // res is null during the unit tests @@ -730,39 +759,42 @@ public abstract class GCParser { // waypoint latitude and longitude latlon = Html.fromHtml(TextUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim(); if (!StringUtils.startsWith(latlon, "???")) { - waypoint.setLatlon(latlon); waypoint.setCoords(new Geopoint(latlon)); } - j++; - if (wpItems.length > j) { - wp = wpItems[j].split("<td"); - } + if (wpItems.length >= j) { + final String[] wpNote = StringUtils.splitByWholeSeparator(wpItems[j + 1], "<td"); + assert wpNote != null; + if (wpNote.length < 4) { + Log.d("GCParser.cacheParseFromText: not enough waypoint columns in table to extract note"); + continue; + } - // waypoint note - waypoint.setNote(TextUtils.getMatch(wp[3], GCConstants.PATTERN_WPNOTE, waypoint.getNote())); + // waypoint note + waypoint.setNote(TextUtils.getMatch(wpNote[3], GCConstants.PATTERN_WPNOTE, waypoint.getNote())); + } cache.addOrChangeWaypoint(waypoint, false); } } } - cache.parseWaypointsFromNote(); - // last check for necessary cache conditions if (StringUtils.isBlank(cache.getGeocode())) { - return ImmutablePair.of(StatusCode.UNKNOWN_ERROR, null); + return UNKNOWN_PARSE_ERROR; } cache.setDetailedUpdatedNow(); return ImmutablePair.of(StatusCode.NO_ERROR, cache); } + @Nullable private static String getNumberString(final String numberWithPunctuation) { return StringUtils.replaceChars(numberWithPunctuation, ".,", ""); } - public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + @Nullable + public static SearchResult searchByNextPage(final SearchResult search, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (search == null) { return null; } @@ -817,14 +849,12 @@ public abstract class GCParser { /** * Possibly hide caches found or hidden by user. This mutates its params argument when possible. * - * @param params - * the parameters to mutate, or null to create a new Parameters if needed - * @param my - * @param addF + * @param params the parameters to mutate, or null to create a new Parameters if needed + * @param my {@code true} if the user's caches must be forcibly included regardless of their settings * @return the original params if not null, maybe augmented with f=1, or a new Parameters with f=1 or null otherwise */ - private static Parameters addFToParams(final Parameters params, final boolean my, final boolean addF) { - if (!my && Settings.isExcludeMyCaches() && addF) { + private static Parameters addFToParams(final Parameters params, final boolean my) { + if (!my && Settings.isExcludeMyCaches()) { if (params == null) { return new Parameters("f", "1"); } @@ -835,22 +865,14 @@ public abstract class GCParser { return params; } - /** - * @param cacheType - * @param listId - * @param showCaptcha - * @param params - * the parameters to add to the request URI - * @param recaptchaReceiver - * @return - */ @Nullable - private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, RecaptchaReceiver recaptchaReceiver) { + private static SearchResult searchByAny(@NonNull final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, final RecaptchaReceiver recaptchaReceiver) { insertCacheType(params, cacheType); final String uri = "http://www.geocaching.com/seek/nearest.aspx"; - final String fullUri = uri + "?" + addFToParams(params, my, true); - final String page = GCLogin.getInstance().getRequestLogged(uri, addFToParams(params, my, true)); + final Parameters paramsWithF = addFToParams(params, my); + final String fullUri = uri + "?" + paramsWithF; + final String page = GCLogin.getInstance().getRequestLogged(uri, paramsWithF); if (StringUtils.isBlank(page)) { Log.e("GCParser.searchByAny: No data from server"); @@ -871,12 +893,12 @@ public abstract class GCParser { return search; } - public static SearchResult searchByCoords(final @NonNull Geopoint coords, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByCoords(final @NonNull Geopoint coords, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { final Parameters params = new Parameters("lat", Double.toString(coords.getLatitude()), "lng", Double.toString(coords.getLongitude())); return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByKeyword(final @NonNull String keyword, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByKeyword(final @NonNull String keyword, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(keyword)) { Log.e("GCParser.searchByKeyword: No keyword given"); return null; @@ -894,7 +916,7 @@ public abstract class GCParser { return false; } - public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByUsername(final String userName, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByUsername: No user name given"); return null; @@ -905,7 +927,7 @@ public abstract class GCParser { return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByPocketQuery(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByPocketQuery(final String pocketGuid, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(pocketGuid)) { Log.e("GCParser.searchByPocket: No guid name given"); return null; @@ -916,7 +938,7 @@ public abstract class GCParser { return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + public static SearchResult searchByOwner(final String userName, @NonNull final CacheType cacheType, final boolean showCaptcha, final RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByOwner: No user name given"); return null; @@ -926,34 +948,6 @@ public abstract class GCParser { return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { - if (StringUtils.isBlank(address)) { - Log.e("GCParser.searchByAddress: No address given"); - return null; - } - try { - final JSONObject response = Network.requestJSON("http://www.geocaching.com/api/geocode", new Parameters("q", address)); - if (response == null) { - return null; - } - if (!StringUtils.equalsIgnoreCase(response.getString("status"), "success")) { - return null; - } - if (!response.has("data")) { - return null; - } - final JSONObject data = response.getJSONObject("data"); - if (data == null) { - return null; - } - return searchByCoords(new Geopoint(data.getDouble("lat"), data.getDouble("lng")), cacheType, showCaptcha, recaptchaReceiver); - } catch (final JSONException e) { - Log.w("GCParser.searchByAddress", e); - } - - return null; - } - @Nullable public static Trackable searchTrackable(final String geocode, final String guid, final String id) { if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) { @@ -990,52 +984,59 @@ public abstract class GCParser { return trackable; } - public static List<PocketQueryList> searchPocketQueryList() { - - final Parameters params = new Parameters(); + /** + * Observable that fetches a list of pocket queries. Returns a single element (which may be an empty list). + * Executes on the network scheduler. + */ + public static final Observable<List<PocketQueryList>> searchPocketQueryListObservable = Observable.defer(new Func0<Observable<List<PocketQueryList>>>() { + @Override + public Observable<List<PocketQueryList>> call() { + final Parameters params = new Parameters(); - final String page = GCLogin.getInstance().getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); + final String page = GCLogin.getInstance().getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); - if (StringUtils.isBlank(page)) { - Log.e("GCParser.searchPocketQueryList: No data from server"); - return null; - } + if (StringUtils.isBlank(page)) { + Log.e("GCParser.searchPocketQueryList: No data from server"); + return Observable.just(Collections.<PocketQueryList>emptyList()); + } - String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); - if (StringUtils.isEmpty(subPage)) { - Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page"); - return Collections.emptyList(); - } + final String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); + if (StringUtils.isEmpty(subPage)) { + Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page"); + return Observable.just(Collections.<PocketQueryList>emptyList()); + } - List<PocketQueryList> list = new ArrayList<>(); + final List<PocketQueryList> list = new ArrayList<>(); - final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage); + final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage); - while (matcherPocket.find()) { - int maxCaches; - try { - maxCaches = Integer.parseInt(matcherPocket.group(1)); - } catch (NumberFormatException e) { - maxCaches = 0; - Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e); + while (matcherPocket.find()) { + int maxCaches; + try { + maxCaches = Integer.parseInt(matcherPocket.group(1)); + } catch (final NumberFormatException e) { + maxCaches = 0; + Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e); + } + final String guid = Html.fromHtml(matcherPocket.group(2)).toString(); + final String name = Html.fromHtml(matcherPocket.group(3)).toString(); + final PocketQueryList pqList = new PocketQueryList(guid, name, maxCaches); + list.add(pqList); } - final String guid = Html.fromHtml(matcherPocket.group(2)).toString(); - final String name = Html.fromHtml(matcherPocket.group(3)).toString(); - final PocketQueryList pqList = new PocketQueryList(guid, name, maxCaches); - list.add(pqList); - } - // just in case, lets sort the resulting list - Collections.sort(list, new Comparator<PocketQueryList>() { + // just in case, lets sort the resulting list + final Collator collator = TextUtils.getCollator(); + Collections.sort(list, new Comparator<PocketQueryList>() { - @Override - public int compare(PocketQueryList left, PocketQueryList right) { - return String.CASE_INSENSITIVE_ORDER.compare(left.getName(), right.getName()); - } - }); + @Override + public int compare(final PocketQueryList left, final PocketQueryList right) { + return collator.compare(left.getName(), right.getName()); + } + }); - return list; - } + return Observable.just(list); + } + }).subscribeOn(RxUtils.networkScheduler); public static ImmutablePair<StatusCode, String> postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, @@ -1061,7 +1062,7 @@ public abstract class GCParser { "__EVENTARGUMENT", "", "__LASTFOCUS", "", "ctl00$ContentBody$LogBookPanel1$ddLogType", Integer.toString(logType.id), - "ctl00$ContentBody$LogBookPanel1$uxDateVisited", GCLogin.getCustomGcDateFormat().format(new GregorianCalendar(year, month - 1, day).getTime()), + "ctl00$ContentBody$LogBookPanel1$uxDateVisited", GCLogin.formatGcCustomDate(year, month, day), "ctl00$ContentBody$LogBookPanel1$uxDateVisited$Month", Integer.toString(month), "ctl00$ContentBody$LogBookPanel1$uxDateVisited$Day", Integer.toString(day), "ctl00$ContentBody$LogBookPanel1$uxDateVisited$Year", Integer.toString(year), @@ -1147,6 +1148,11 @@ public abstract class GCParser { Log.e("GCParser.postLog.confim", e); } + if (page == null) { + Log.e("GCParser.postLog: didn't get response"); + return new ImmutablePair<>(StatusCode.LOG_POST_ERROR, ""); + } + try { final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK1, page); @@ -1160,7 +1166,7 @@ public abstract class GCParser { gcLogin.getLoginStatus(page); // the log-successful-page contains still the old value if (gcLogin.getActualCachesFound() >= 0) { - gcLogin.setActualCachesFound(gcLogin.getActualCachesFound() + 1); + gcLogin.setActualCachesFound(gcLogin.getActualCachesFound() + (logType.isFoundLog() ? 1 : 0)); } final String logID = TextUtils.getMatch(page, GCConstants.PATTERN_LOG_IMAGE_UPLOAD, ""); @@ -1211,6 +1217,11 @@ public abstract class GCParser { final File image = new File(imageUri.getPath()); final String response = Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$ImageUploadControl1$uxFileUpload", "image/jpeg", image)); + if (response == null) { + Log.e("GCParser.uploadLogIMage: didn't get response for image upload"); + return ImmutablePair.of(StatusCode.LOGIMAGE_POST_ERROR, null); + } + final MatcherWrapper matcherUrl = new MatcherWrapper(GCConstants.PATTERN_IMAGE_UPLOAD_URL, response); if (matcherUrl.find()) { @@ -1257,7 +1268,7 @@ public abstract class GCParser { params.put("ctl00$ContentBody$LogBookPanel1$uxDateVisited", ""); } else { params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged", Integer.toString(month) + "/" + Integer.toString(day) + "/" + Integer.toString(year)); - params.put("ctl00$ContentBody$LogBookPanel1$uxDateVisited", GCLogin.getCustomGcDateFormat().format(new GregorianCalendar(year, month - 1, day).getTime())); + params.put("ctl00$ContentBody$LogBookPanel1$uxDateVisited", GCLogin.formatGcCustomDate(year, month, day)); } params.put( "ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Day", Integer.toString(day), @@ -1417,7 +1428,10 @@ public abstract class GCParser { } private static String getUserToken(final Geocache cache) { - final String page = requestHtmlPage(cache.getGeocode(), null, "n"); + return parseUserToken(requestHtmlPage(cache.getGeocode(), null, "n")); + } + + private static String parseUserToken(final String page) { return TextUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, ""); } @@ -1483,7 +1497,7 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse trackable owner name - Log.w("GCParser.parseTrackable: Failed to parse trackable owner name"); + Log.w("GCParser.parseTrackable: Failed to parse trackable owner name", e); } // trackable origin @@ -1514,20 +1528,20 @@ public abstract class GCParser { } } catch (final RuntimeException e) { // failed to parse trackable last known place - Log.w("GCParser.parseTrackable: Failed to parse trackable last known place"); + Log.w("GCParser.parseTrackable: Failed to parse trackable last known place", e); } // released date - can be missing on the page final String releaseString = TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null); if (releaseString != null) { try { - trackable.setReleased(dateTbIn1.parse(releaseString)); - } catch (ParseException e) { + trackable.setReleased(DATE_TB_IN_1.parse(releaseString)); + } catch (final ParseException ignored) { if (trackable.getReleased() == null) { try { - trackable.setReleased(dateTbIn2.parse(releaseString)); - } catch (ParseException e1) { - Log.e("Could not parse trackable release " + releaseString); + trackable.setReleased(DATE_TB_IN_2.parse(releaseString)); + } catch (final ParseException e) { + Log.e("Could not parse trackable release " + releaseString, e); } } } @@ -1538,14 +1552,14 @@ public abstract class GCParser { if (null != distance) { try { trackable.setDistance(DistanceParser.parseDistance(distance, - !Settings.isUseImperialUnits())); + !Settings.useImperialUnits())); } catch (final NumberFormatException e) { Log.e("GCParser.parseTrackable: Failed to parse distance", e); } } // trackable goal - trackable.setGoal(convertLinks(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal()))); + trackable.setGoal(HtmlUtils.removeExtraParagraph(convertLinks(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())))); // trackable details & image try { @@ -1558,12 +1572,12 @@ public abstract class GCParser { trackable.setImage(StringUtils.replace(image, "/display/", "/large/")); } if (StringUtils.isNotEmpty(details) && !StringUtils.equals(details, "No additional details available.")) { - trackable.setDetails(convertLinks(details)); + trackable.setDetails(HtmlUtils.removeExtraParagraph(convertLinks(details))); } } } catch (final RuntimeException e) { // failed to parse trackable details & image - Log.w("GCParser.parseTrackable: Failed to parse trackable details & image"); + Log.w("GCParser.parseTrackable: Failed to parse trackable details & image", e); } if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) { trackable.setDetails(CgeoApplication.getInstance().getString(R.string.trackable_not_activated)); @@ -1585,7 +1599,7 @@ public abstract class GCParser { long date = 0; try { date = GCLogin.parseGcCustomDate(matcherLogs.group(2)).getTime(); - } catch (final ParseException e) { + } catch (final ParseException ignored) { } final LogEntry logDone = new LogEntry( @@ -1630,7 +1644,7 @@ public abstract class GCParser { return trackable; } - private static String convertLinks(String input) { + private static String convertLinks(final String input) { if (input == null) { return null; } @@ -1656,23 +1670,19 @@ public abstract class GCParser { /** * Extract special logs (friends, own) through seperate request. * - * @param page - * The page to extrat userToken from - * @param logType - * The logType to request + * @param userToken the user token extracted from the web page + * @param logType the logType to request * @return Observable<LogEntry> The logs */ - private static Observable<LogEntry> getLogs(final String page, final Logs logType) { + private static Observable<LogEntry> getLogs(final String userToken, final Logs logType) { + if (userToken.isEmpty()) { + Log.e("GCParser.loadLogsFromDetails: unable to extract userToken"); + return Observable.empty(); + } + return Observable.defer(new Func0<Observable<LogEntry>>() { @Override public Observable<LogEntry> call() { - final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page); - if (!userTokenMatcher.find()) { - Log.e("GCParser.loadLogsFromDetails: unable to extract userToken"); - return Observable.empty(); - } - - final String userToken = userTokenMatcher.group(1); final Parameters params = new Parameters( "tkn", userToken, "idx", "1", @@ -1691,77 +1701,67 @@ public abstract class GCParser { Log.e("GCParser.loadLogsFromDetails: error " + statusCode + " when requesting log information"); return Observable.empty(); } - String rawResponse = Network.getResponseData(response); - if (rawResponse == null) { + final InputStream responseStream = Network.getResponseStream(response); + if (responseStream == null) { Log.e("GCParser.loadLogsFromDetails: unable to read whole response"); return Observable.empty(); } - return parseLogs(logType != Logs.ALL, rawResponse); + return parseLogs(logType != Logs.ALL, responseStream); } }).subscribeOn(RxUtils.networkScheduler); } - private static Observable<LogEntry> parseLogs(final boolean markAsFriendsLog, final String rawResponse) { + private static Observable<LogEntry> parseLogs(final boolean markAsFriendsLog, final InputStream responseStream) { return Observable.create(new OnSubscribe<LogEntry>() { @Override public void call(final Subscriber<? super LogEntry> subscriber) { - // for non logged in users the log book is not shown - if (StringUtils.isBlank(rawResponse)) { - subscriber.onCompleted(); - return; - } - try { - final JSONObject resp = new JSONObject(rawResponse); - if (!resp.getString("status").equals("success")) { - Log.e("GCParser.loadLogsFromDetails: status is " + resp.getString("status")); + final ObjectNode resp = (ObjectNode) JsonUtils.reader.readTree(responseStream); + if (!resp.path("status").asText().equals("success")) { + Log.e("GCParser.loadLogsFromDetails: status is " + resp.path("status").asText("[absent]")); subscriber.onCompleted(); return; } - final JSONArray data = resp.getJSONArray("data"); - - for (int index = 0; index < data.length(); index++) { - final JSONObject entry = data.getJSONObject(index); - + final ArrayNode data = (ArrayNode) resp.get("data"); + for (final JsonNode entry: data) { // FIXME: use the "LogType" field instead of the "LogTypeImage" one. - final String logIconNameExt = entry.optString("LogTypeImage", ".gif"); + final String logIconNameExt = entry.path("LogTypeImage").asText(".gif"); final String logIconName = logIconNameExt.substring(0, logIconNameExt.length() - 4); - long date = 0; + final long date; try { - date = GCLogin.parseGcCustomDate(entry.getString("Visited")).getTime(); - } catch (final ParseException e) { - Log.e("GCParser.loadLogsFromDetails: failed to parse log date."); + date = GCLogin.parseGcCustomDate(entry.get("Visited").asText()).getTime(); + } catch (ParseException | NullPointerException e) { + Log.e("GCParser.loadLogsFromDetails: failed to parse log date", e); + continue; } // TODO: we should update our log data structure to be able to record // proper coordinates, and make them clickable. In the meantime, it is // better to integrate those coordinates into the text rather than not // display them at all. - final String latLon = entry.getString("LatLonString"); - final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "<br/><br/>")) + TextUtils.removeControlCharacters(entry.getString("LogText")); + final String latLon = entry.path("LatLonString").asText(); + final String logText = (StringUtils.isEmpty(latLon) ? "" : (latLon + "<br/><br/>")) + TextUtils.removeControlCharacters(entry.path("LogText").asText()); final LogEntry logDone = new LogEntry( - TextUtils.removeControlCharacters(entry.getString("UserName")), + TextUtils.removeControlCharacters(entry.path("UserName").asText()), date, LogType.getByIconName(logIconName), logText); - logDone.found = entry.getInt("GeocacheFindCount"); + logDone.found = entry.path("GeocacheFindCount").asInt(); logDone.friend = markAsFriendsLog; - final JSONArray images = entry.getJSONArray("Images"); - for (int i = 0; i < images.length(); i++) { - final JSONObject image = images.getJSONObject(i); - final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.getString("FileName"); - final String title = TextUtils.removeControlCharacters(image.getString("Name")); + final ArrayNode images = (ArrayNode) entry.get("Images"); + for (final JsonNode image: images) { + final String url = "http://imgcdn.geocaching.com/cache/log/large/" + image.path("FileName").asText(); + final String title = TextUtils.removeControlCharacters(image.path("Name").asText()); final Image logImage = new Image(url, title); logDone.addLogImage(logImage); } subscriber.onNext(logDone); } - } catch (final JSONException e) { - // failed to parse logs + } catch (final IOException e) { Log.w("GCParser.loadLogsFromDetails: Failed to parse cache logs", e); } subscriber.onCompleted(); @@ -1770,7 +1770,7 @@ public abstract class GCParser { } @NonNull - public static List<LogType> parseTypes(String page) { + public static List<LogType> parseTypes(final String page) { if (StringUtils.isEmpty(page)) { return Collections.emptyList(); } @@ -1801,9 +1801,10 @@ public abstract class GCParser { return types; } + @NonNull public static List<TrackableLog> parseTrackableLog(final String page) { if (StringUtils.isEmpty(page)) { - return null; + return Collections.emptyList(); } String table = StringUtils.substringBetween(page, "<table id=\"tblTravelBugs\"", "</table>"); @@ -1816,7 +1817,7 @@ public abstract class GCParser { table = StringUtils.substringBetween(table, "<tbody>", "</tbody>"); if (StringUtils.isBlank(table)) { Log.e("GCParser.parseTrackableLog: tbody not found on page"); - return null; + return Collections.emptyList(); } final List<TrackableLog> trackableLogs = new ArrayList<>(); @@ -1865,16 +1866,12 @@ public abstract class GCParser { return; } - final Observable<LogEntry> logs = getLogs(page, Logs.ALL); - Observable<LogEntry> specialLogs; - if (Settings.isFriendLogsWanted()) { - CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); - specialLogs = Observable.merge(getLogs(page, Logs.FRIENDS), - getLogs(page, Logs.OWN)); - } else { - CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); - specialLogs = Observable.empty(); - } + CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); + final String userToken = parseUserToken(page); + final Observable<LogEntry> logs = getLogs(userToken, Logs.ALL); + final Observable<LogEntry> ownLogs = getLogs(userToken, Logs.OWN).cache(); + final Observable<LogEntry> specialLogs = Settings.isFriendLogsWanted() ? + Observable.merge(getLogs(userToken, Logs.FRIENDS), ownLogs) : Observable.<LogEntry>empty(); final Observable<List<LogEntry>> mergedLogs = Observable.zip(logs.toList(), specialLogs.toList(), new Func2<List<LogEntry>, List<LogEntry>, List<LogEntry>>() { @Override @@ -1886,9 +1883,19 @@ public abstract class GCParser { mergedLogs.subscribe(new Action1<List<LogEntry>>() { @Override public void call(final List<LogEntry> logEntries) { - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), logEntries); + DataStore.saveLogs(cache.getGeocode(), logEntries); } }); + if (cache.isFound() && cache.getVisitedDate() == 0) { + ownLogs.subscribe(new Action1<LogEntry>() { + @Override + public void call(final LogEntry logEntry) { + if (logEntry.type == LogType.FOUND_IT) { + cache.setVisitedDate(logEntry.date); + } + } + }); + } if (Settings.isRatingWanted() && !CancellableHandler.isCancelled(handler)) { CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote); @@ -1901,7 +1908,7 @@ public abstract class GCParser { } // Wait for completion of logs parsing, retrieving and merging - mergedLogs.toBlocking().last(); + RxUtils.waitForCompletion(mergedLogs); } /** @@ -1923,77 +1930,82 @@ public abstract class GCParser { } } - public static boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) { + public static boolean uploadModifiedCoordinates(final Geocache cache, final Geopoint wpt) { return editModifiedCoordinates(cache, wpt); } - public static boolean deleteModifiedCoordinates(Geocache cache) { + public static boolean deleteModifiedCoordinates(final Geocache cache) { return editModifiedCoordinates(cache, null); } - public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) { + public static boolean editModifiedCoordinates(final Geocache cache, final Geopoint wpt) { final String userToken = getUserToken(cache); if (StringUtils.isEmpty(userToken)) { return false; } - try { - JSONObject jo; - if (wpt != null) { - jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken) - .put("data", new JSONObject() - .put("lat", wpt.getLatitudeE6() / 1E6) - .put("lng", wpt.getLongitudeE6() / 1E6)))); - } else { - jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken))); - } - - final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate"; + final ObjectNode jo = new ObjectNode(JsonUtils.factory); + final ObjectNode dto = jo.putObject("dto").put("ut", userToken); + if (wpt != null) { + dto.putObject("data").put("lat", wpt.getLatitudeE6() / 1E6).put("lng", wpt.getLongitudeE6() / 1E6); + } - final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; - final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); - Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); + final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate"; - if (response != null && response.getStatusLine().getStatusCode() == 200) { - Log.i("GCParser.editModifiedCoordinates - edited on GC.com"); - return true; - } + final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; + final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); - } catch (final JSONException e) { - Log.e("Unknown exception with json wrap code", e); + if (response != null && response.getStatusLine().getStatusCode() == 200) { + Log.i("GCParser.editModifiedCoordinates - edited on GC.com"); + return true; } + Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords"); return false; } - public static boolean uploadPersonalNote(Geocache cache) { + public static boolean uploadPersonalNote(final Geocache cache) { final String userToken = getUserToken(cache); if (StringUtils.isEmpty(userToken)) { return false; } - try { - final JSONObject jo = new JSONObject() - .put("dto", (new JSONObject() - .put("et", StringUtils.defaultString(cache.getPersonalNote())) - .put("ut", userToken))); - - final String uriSuffix = "SetUserCacheNote"; + final ObjectNode jo = new ObjectNode(JsonUtils.factory); + jo.putObject("dto").put("et", StringUtils.defaultString(cache.getPersonalNote())).put("ut", userToken); - final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; - final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); - Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString()); + final String uriSuffix = "SetUserCacheNote"; - if (response != null && response.getStatusLine().getStatusCode() == 200) { - Log.i("GCParser.uploadPersonalNote - uploaded to GC.com"); - return true; - } + final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/"; + final HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo); - } catch (final JSONException e) { - Log.e("Unknown exception with json wrap code", e); + if (response != null && response.getStatusLine().getStatusCode() == 200) { + Log.i("GCParser.uploadPersonalNote - uploaded to GC.com"); + return true; } + Log.e("GCParser.uploadPersonalNote - cannot upload personal note"); return false; } + public static boolean ignoreCache(@NonNull final Geocache cache) { + final String uri = "http://www.geocaching.com/bookmarks/ignore.aspx?guid=" + cache.getGuid() + "&WptTypeID=" + cache.getType().wptTypeId; + final String page = GCLogin.getInstance().postRequestLogged(uri, null); + + if (StringUtils.isBlank(page)) { + Log.e("GCParser.ignoreCache: No data from server"); + return false; + } + + final String[] viewstates = GCLogin.getViewstates(page); + + final Parameters params = new Parameters( + "__EVENTTARGET", "", + "__EVENTARGUMENT", "", + "ctl00$ContentBody$btnYes", "Yes. Ignore it."); + + GCLogin.putViewstates(params, viewstates); + final String response = Network.getResponseData(Network.postRequest(uri, params)); + + return StringUtils.contains(response, "<p class=\"Success\">"); + } } diff --git a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java index eba9301..071c3b0 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java +++ b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java @@ -1,5 +1,7 @@ package cgeo.geocaching.connector.gc; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; public class GCSmiliesProvider { public enum Smiley { @@ -24,9 +26,10 @@ public class GCSmiliesProvider { DISAPPROVE("V"), QUESTION("?"); + @NonNull public final String text; - Smiley(final String text) { + Smiley(@NonNull final String text) { this.text = text; } @@ -35,12 +38,14 @@ public class GCSmiliesProvider { } } + @NonNull public static Smiley[] getSmilies() { return Smiley.values(); } - public static Smiley getSmiley(int itemId) { - for (Smiley smiley : getSmilies()) { + @Nullable + public static Smiley getSmiley(final int itemId) { + for (final Smiley smiley : getSmilies()) { if (smiley.getItemId() == itemId) { return smiley; } diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java index c6a2afc..95bb77d 100644 --- a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java +++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java @@ -10,7 +10,7 @@ import android.graphics.Bitmap; * icon decoder for cache icons * */ -public abstract class IconDecoder { +abstract class IconDecoder { private static final int CT_TRADITIONAL = 0; private static final int CT_MULTI = 1; private static final int CT_MYSTERY = 2; @@ -25,7 +25,7 @@ public abstract class IconDecoder { private static final int CT_VIRTUAL = 11; private static final int CT_LETTERBOX = 12; - public static boolean parseMapPNG(final Geocache cache, Bitmap bitmap, UTFGridPosition xy, int zoomlevel) { + static boolean parseMapPNG(final Geocache cache, final Bitmap bitmap, final UTFGridPosition xy, final int zoomlevel) { final int topX = xy.getX() * 4; final int topY = xy.getY() * 4; final int bitmapWidth = bitmap.getWidth(); @@ -43,24 +43,24 @@ public abstract class IconDecoder { numberOfDetections = 13; } - int[] pngType = new int[numberOfDetections]; + final int[] pngType = new int[numberOfDetections]; for (int x = topX; x < topX + 4; x++) { for (int y = topY; y < topY + 4; y++) { - int color = bitmap.getPixel(x, y); + final int color = bitmap.getPixel(x, y); if ((color >>> 24) != 255) { continue; //transparent pixels (or semi_transparent) are only shadows of border } - int r = (color & 0xFF0000) >> 16; - int g = (color & 0xFF00) >> 8; - int b = color & 0xFF; + final int r = (color & 0xFF0000) >> 16; + final int g = (color & 0xFF00) >> 8; + final int b = color & 0xFF; if (isPixelDuplicated(r, g, b, zoomlevel)) { continue; } - int type; + final int type; if (zoomlevel < 12) { type = getCacheTypeFromPixel11(r, g, b); } else { @@ -143,7 +143,7 @@ public abstract class IconDecoder { * zoom level of map * @return true if parsing should not be performed */ - private static boolean isPixelDuplicated(int r, int g, int b, int zoomlevel) { + private static boolean isPixelDuplicated(final int r, final int g, final int b, final int zoomlevel) { if (zoomlevel < 12) { if (((r == g) && (g == b)) || ((r == 233) && (g == 233) && (b == 234))) { return true; @@ -194,7 +194,7 @@ public abstract class IconDecoder { * Blue component of pixel (from 0 - 255) * @return Value from 0 to 6 representing detected type or state of the cache. */ - private static int getCacheTypeFromPixel13(int r, int g, int b) { + private static int getCacheTypeFromPixel13(final int r, final int g, final int b) { if (b < 130) { if (r < 41) { return CT_MYSTERY; @@ -256,7 +256,7 @@ public abstract class IconDecoder { * Blue component of pixel (from 0 - 255) * @return Value from 0 to 6 representing detected type or state of the cache. */ - private static int getCacheTypeFromPixel14(int r, int g, int b) { + private static int getCacheTypeFromPixel14(final int r, final int g, final int b) { if (b < 128) { if (r < 214) { if (b < 37) { @@ -489,7 +489,7 @@ public abstract class IconDecoder { * Blue component of pixel (from 0 - 255) * @return Value from 0 to 4 representing detected type or state of the cache. */ - private static int getCacheTypeFromPixel11(int r, int g, int b) { + private static int getCacheTypeFromPixel11(final int r, final int g, final int b) { if (g < 136) { if (r < 90) { return g < 111 ? CT_MYSTERY : CT_TRADITIONAL; diff --git a/main/src/cgeo/geocaching/connector/gc/MapTokens.java b/main/src/cgeo/geocaching/connector/gc/MapTokens.java index 78ce4cb..b41533d 100644 --- a/main/src/cgeo/geocaching/connector/gc/MapTokens.java +++ b/main/src/cgeo/geocaching/connector/gc/MapTokens.java @@ -4,11 +4,11 @@ import android.util.Pair; /** * Wrapper type to make map tokens more type safe than with a String array. - * + * */ public final class MapTokens extends Pair<String, String> { - public MapTokens(String userSession, String sessionToken) { + MapTokens(final String userSession, final String sessionToken) { super(userSession, sessionToken); } diff --git a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java index 5bcfd17..1258ddd 100644 --- a/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java +++ b/main/src/cgeo/geocaching/connector/gc/RecaptchaHandler.java @@ -11,7 +11,7 @@ import cgeo.geocaching.utils.RxUtils; import org.apache.commons.io.IOUtils; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; @@ -42,9 +42,9 @@ public class RecaptchaHandler extends Handler { } private void loadChallenge(final ImageView imageView, final View reloadButton, final boolean needsFetch) { - final Observable<Bitmap> captcha = Observable.defer(new Func0<Observable<? extends Bitmap>>() { + final Observable<Bitmap> captcha = Observable.defer(new Func0<Observable<Bitmap>>() { @Override - public Observable<? extends Bitmap> call() { + public Observable<Bitmap> call() { if (needsFetch) { recaptchaReceiver.fetchChallenge(); } @@ -53,7 +53,7 @@ public class RecaptchaHandler extends Handler { if (is != null) { try { final Bitmap img = BitmapFactory.decodeStream(is); - return Observable.from(img); + return Observable.just(img); } catch (final Exception e) { Log.e("RecaptchaHandler.getCaptcha", e); return Observable.error(e); @@ -64,7 +64,7 @@ public class RecaptchaHandler extends Handler { return Observable.empty(); } }); - AndroidObservable.bindActivity(activity, captcha).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<Bitmap>() { + AppObservable.bindActivity(activity, captcha).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<Bitmap>() { @Override public void call(final Bitmap bitmap) { imageView.setImageBitmap(bitmap); diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index 18fe65c..dd6371b 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -1,8 +1,8 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.ICoordinates; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.utils.LeastRecentlyUsedSet; @@ -15,7 +15,6 @@ import org.eclipse.jdt.annotation.NonNull; import rx.Observable; import rx.functions.Func0; -import rx.util.async.Async; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -35,13 +34,13 @@ import java.util.Set; */ public class Tile { - public static final int TILE_SIZE = 256; - public static final int ZOOMLEVEL_MAX = 18; + static final int TILE_SIZE = 256; + static final int ZOOMLEVEL_MAX = 18; public static final int ZOOMLEVEL_MIN = 0; public static final int ZOOMLEVEL_MIN_PERSONALIZED = 12; - static final int[] NUMBER_OF_TILES = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1]; - static final int[] NUMBER_OF_PIXELS = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1]; + private static final int[] NUMBER_OF_TILES = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1]; + private static final int[] NUMBER_OF_PIXELS = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1]; static { for (int z = ZOOMLEVEL_MIN; z <= ZOOMLEVEL_MAX; z++) { NUMBER_OF_TILES[z] = 1 << z; @@ -56,11 +55,11 @@ public class Tile { private final int zoomLevel; private final Viewport viewPort; - public Tile(Geopoint origin, int zoomlevel) { + public Tile(final Geopoint origin, final int zoomlevel) { this(calcX(origin, clippedZoomlevel(zoomlevel)), calcY(origin, clippedZoomlevel(zoomlevel)), clippedZoomlevel(zoomlevel)); } - private Tile(int tileX, int tileY, int zoomlevel) { + private Tile(final int tileX, final int tileY, final int zoomlevel) { this.zoomLevel = clippedZoomlevel(zoomlevel); @@ -74,7 +73,7 @@ public class Tile { return zoomLevel; } - private static int clippedZoomlevel(int zoomlevel) { + private static int clippedZoomlevel(final int zoomlevel) { return Math.max(Math.min(zoomlevel, ZOOMLEVEL_MAX), ZOOMLEVEL_MIN); } @@ -95,7 +94,7 @@ public class Tile { */ private static int calcY(final Geopoint origin, final int zoomlevel) { // Optimization from Bing - double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude())); + final double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude())); // The cut of the fractional part instead of rounding to the nearest integer is intentional and part of the algorithm return (int) ((0.5 - Math.log((1 + sinLatRad) / (1 - sinLatRad)) / (4 * Math.PI)) * NUMBER_OF_TILES[zoomlevel]); } @@ -115,13 +114,13 @@ public class Tile { * href="http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers">Cloudmade</a> */ @NonNull - public Geopoint getCoord(UTFGridPosition pos) { + Geopoint getCoord(final UTFGridPosition pos) { - double pixX = tileX * TILE_SIZE + pos.x * 4; - double pixY = tileY * TILE_SIZE + pos.y * 4; + final double pixX = tileX * TILE_SIZE + pos.x * 4; + final double pixY = tileY * TILE_SIZE + pos.y * 4; - double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomLevel]) - 180.0; - double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomLevel]))); + final double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomLevel]) - 180.0; + final double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomLevel]))); return new Geopoint(Math.toDegrees(latRad), lonDeg); } @@ -144,17 +143,16 @@ public class Tile { * First point * @param right * Second point - * @return */ - public static int calcZoomLon(final Geopoint left, final Geopoint right, final int numberOfTiles) { + static int calcZoomLon(final Geopoint left, final Geopoint right, final int numberOfTiles) { int zoom = (int) Math.floor( Math.log(360.0 * numberOfTiles / (2.0 * Math.abs(left.getLongitude() - right.getLongitude()))) / Math.log(2) ); - Tile tileLeft = new Tile(left, zoom); - Tile tileRight = new Tile(right, zoom); + final Tile tileLeft = new Tile(left, zoom); + final Tile tileRight = new Tile(right, zoom); if (Math.abs(tileLeft.tileX - tileRight.tileX) < (numberOfTiles - 1)) { zoom += 1; @@ -177,9 +175,8 @@ public class Tile { * First point * @param top * Second point - * @return */ - public static int calcZoomLat(final Geopoint bottom, final Geopoint top, final int numberOfTiles) { + static int calcZoomLat(final Geopoint bottom, final Geopoint top, final int numberOfTiles) { int zoom = (int) Math.ceil( Math.log(2.0 * Math.PI * numberOfTiles / ( @@ -190,8 +187,8 @@ public class Tile { ) / Math.log(2) ); - Tile tileBottom = new Tile(bottom, zoom); - Tile tileTop = new Tile(top, zoom); + final Tile tileBottom = new Tile(bottom, zoom); + final Tile tileTop = new Tile(top, zoom); if (Math.abs(tileBottom.tileY - tileTop.tileY) > (numberOfTiles - 1)) { zoom -= 1; @@ -200,7 +197,7 @@ public class Tile { return Math.min(zoom, ZOOMLEVEL_MAX); } - private static double tanGrad(double angleGrad) { + private static double tanGrad(final double angleGrad) { return Math.tan(angleGrad / 180.0 * Math.PI); } @@ -208,15 +205,13 @@ public class Tile { * Calculates the inverted hyperbolic sine * (after Bronstein, Semendjajew: Taschenbuch der Mathematik) * - * @param x - * @return */ - private static double asinh(double x) { + private static double asinh(final double x) { return Math.log(x + Math.sqrt(x * x + 1.0)); } @Override - public boolean equals(Object o) { + public boolean equals(final Object o) { if (this == o) { return true; } @@ -238,14 +233,15 @@ public class Tile { * * @return An observable with one element, which may be <tt>null</tt>. */ - public static Observable<String> requestMapInfo(final String url, final Parameters params, final String referer) { + + static Observable<String> requestMapInfo(final String url, final Parameters params, final String referer) { final HttpResponse response = Network.getRequest(url, params, new Parameters("Referer", referer)); - return Async.start(new Func0<String>() { + return Observable.defer(new Func0<Observable<String>>() { @Override - public String call() { - return Network.getResponseData(response); + public Observable<String> call() { + return Observable.just(Network.getResponseData(response)); } - }, RxUtils.networkScheduler); + }).subscribeOn(RxUtils.networkScheduler); } /** Request .png image for a tile. Return as soon as the request has been made, before the answer has been @@ -253,19 +249,19 @@ public class Tile { * * @return An observable with one element, which may be <tt>null</tt>. */ - public static Observable<Bitmap> requestMapTile(final Parameters params) { + static Observable<Bitmap> requestMapTile(final Parameters params) { final HttpResponse response = Network.getRequest(GCConstants.URL_MAP_TILE, params, new Parameters("Referer", GCConstants.URL_LIVE_MAP)); - return Async.start(new Func0<Bitmap>() { + return Observable.defer(new Func0<Observable<Bitmap>>() { @Override - public Bitmap call() { + public Observable<Bitmap> call() { try { - return response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null; - } catch (IOException e) { + return Observable.just(response != null ? BitmapFactory.decodeStream(response.getEntity().getContent()) : null); + } catch (final IOException e) { Log.e("Tile.requestMapTile() ", e); - return null; + return Observable.just(null); } } - }, RxUtils.computationScheduler); + }).subscribeOn(RxUtils.computationScheduler); } public boolean containsPoint(final @NonNull ICoordinates point) { @@ -280,8 +276,6 @@ public class Tile { * Calculate needed tiles for the given viewport to cover it with * max 2x2 tiles * - * @param viewport - * @return */ protected static Set<Tile> getTilesForViewport(final Viewport viewport) { return getTilesForViewport(viewport, 2, Tile.ZOOMLEVEL_MIN); @@ -292,26 +286,22 @@ public class Tile { * You can define the minimum number of tiles on the longer axis * and/or the minimum zoom level. * - * @param viewport - * @param tilesOnAxis - * @param minZoom - * @return */ protected static Set<Tile> getTilesForViewport(final Viewport viewport, final int tilesOnAxis, final int minZoom) { - Set<Tile> tiles = new HashSet<>(); - int zoom = Math.max( + final Set<Tile> tiles = new HashSet<>(); + final int zoom = Math.max( Math.min(Tile.calcZoomLon(viewport.bottomLeft, viewport.topRight, tilesOnAxis), Tile.calcZoomLat(viewport.bottomLeft, viewport.topRight, tilesOnAxis)), minZoom); - Tile tileBottomLeft = new Tile(viewport.bottomLeft, zoom); - Tile tileTopRight = new Tile(viewport.topRight, zoom); + final Tile tileBottomLeft = new Tile(viewport.bottomLeft, zoom); + final Tile tileTopRight = new Tile(viewport.topRight, zoom); - int xLow = Math.min(tileBottomLeft.getX(), tileTopRight.getX()); - int xHigh = Math.max(tileBottomLeft.getX(), tileTopRight.getX()); + final int xLow = Math.min(tileBottomLeft.getX(), tileTopRight.getX()); + final int xHigh = Math.max(tileBottomLeft.getX(), tileTopRight.getX()); - int yLow = Math.min(tileBottomLeft.getY(), tileTopRight.getY()); - int yHigh = Math.max(tileBottomLeft.getY(), tileTopRight.getY()); + final int yLow = Math.min(tileBottomLeft.getY(), tileTopRight.getY()); + final int yHigh = Math.max(tileBottomLeft.getY(), tileTopRight.getY()); for (int xNum = xLow; xNum <= xHigh; xNum++) { for (int yNum = yLow; yNum <= yHigh; yNum++) { @@ -324,8 +314,6 @@ public class Tile { public static class TileCache extends LeastRecentlyUsedSet<Tile> { - private static final long serialVersionUID = -1942301031192719547L; - public TileCache() { super(64); } diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java index 89a3de8..4db0519 100644 --- a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java +++ b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java @@ -3,22 +3,22 @@ package cgeo.geocaching.connector.gc; import java.util.List; /** - * + * * @see <a href="https://github.com/mapbox/mbtiles-spec/blob/master/1.1/utfgrid.md">Mapbox</a> - * + * */ -public final class UTFGrid { +final class UTFGrid { - public static final int GRID_MAXX = 63; - public static final int GRID_MAXY = 63; + static final int GRID_MAXX = 63; + static final int GRID_MAXY = 63; /** Calculate from a list of positions (x/y) the coords */ - public static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) { + static UTFGridPosition getPositionInGrid(final List<UTFGridPosition> positions) { int minX = GRID_MAXX; int maxX = 0; int minY = GRID_MAXY; int maxY = 0; - for (UTFGridPosition pos : positions) { + for (final UTFGridPosition pos : positions) { minX = Math.min(minX, pos.x); maxX = Math.max(maxX, pos.x); minY = Math.min(minY, pos.y); diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java index eff193a..f5cd208 100644 --- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java +++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java @@ -8,13 +8,13 @@ import java.util.regex.Pattern; /** * Representation of a position inside an UTFGrid */ -public final class UTFGridPosition { +final class UTFGridPosition { - public final int x; - public final int y; + final int x; + final int y; private final static Pattern PATTERN_JSON_KEY = Pattern.compile("[^\\d]*" + "(\\d+),\\s*(\\d+)" + "[^\\d]*"); // (12, 34) - public UTFGridPosition(final int x, final int y) { + UTFGridPosition(final int x, final int y) { if (x < 0 || x > UTFGrid.GRID_MAXX) { throw new IllegalArgumentException("x outside bounds"); } @@ -36,9 +36,8 @@ public final class UTFGridPosition { /** * @param key * Key in the format (xx, xx) - * @return */ - static UTFGridPosition fromString(String key) { + static UTFGridPosition fromString(final String key) { final MatcherWrapper matcher = new MatcherWrapper(UTFGridPosition.PATTERN_JSON_KEY, key); try { if (matcher.matches()) { @@ -46,7 +45,7 @@ public final class UTFGridPosition { final int y = Integer.parseInt(matcher.group(2)); return new UTFGridPosition(x, y); } - } catch (NumberFormatException e) { + } catch (final NumberFormatException ignored) { } return new UTFGridPosition(0, 0); } diff --git a/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java b/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java index 71adcbd..204fc89 100644 --- a/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java +++ b/main/src/cgeo/geocaching/connector/gc/UncertainProperty.java @@ -4,18 +4,17 @@ package cgeo.geocaching.connector.gc; /** * Property with certainty. When merging properties, the one with higher certainty wins. * - * @param <T> */ public class UncertainProperty<T> { private final T value; private final int certaintyLevel; - public UncertainProperty(T value) { + public UncertainProperty(final T value) { this(value, Tile.ZOOMLEVEL_MAX + 1); } - public UncertainProperty(T value, int certaintyLevel) { + public UncertainProperty(final T value, final int certaintyLevel) { this.value = value; this.certaintyLevel = certaintyLevel; } @@ -42,7 +41,7 @@ public class UncertainProperty<T> { return this; } - public static <T> UncertainProperty<T> getMergedProperty(UncertainProperty<T> property, UncertainProperty<T> otherProperty) { + public static <T> UncertainProperty<T> getMergedProperty(final UncertainProperty<T> property, final UncertainProperty<T> otherProperty) { if (null == property) { return otherProperty; } diff --git a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java index acf7b48..5e5151a 100644 --- a/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java +++ b/main/src/cgeo/geocaching/connector/oc/IOCAuthParams.java @@ -7,7 +7,6 @@ public interface IOCAuthParams { /** * The site name: 'www.opencaching...' * - * @return */ @NonNull String getSite(); @@ -15,56 +14,48 @@ public interface IOCAuthParams { /** * ResId of the Consumer key * - * @return */ int getCKResId(); /** * ResId of the Consumer secret * - * @return */ int getCSResId(); /** * ResId of the Authorization title * - * @return */ int getAuthTitleResId(); /** * Preference key of the public token * - * @return */ int getTokenPublicPrefKey(); /** * Preference key of the secret token * - * @return */ int getTokenSecretPrefKey(); /** * Preference key of the temporary public token (OAuth) * - * @return */ int getTempTokenPublicPrefKey(); /** * Preference key of the temporary secret token (OAuth) * - * @return */ int getTempTokenSecretPrefKey(); /** * The URI to use as a callback (OAuth) * - * @return */ @NonNull String getCallbackUri(); diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java index 284234e..a2322e0 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java @@ -31,7 +31,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { private final ApiSupport apiSupport; private final String licenseString; - public OCApiConnector(String name, String host, String prefix, String cK, String licenseString, ApiSupport apiSupport) { + public OCApiConnector(final String name, final String host, final String prefix, final String cK, final String licenseString, final ApiSupport apiSupport) { super(name, host, prefix); this.cK = cK; this.apiSupport = apiSupport; @@ -39,10 +39,16 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { } public void addAuthentication(final Parameters params) { - params.put(CryptUtils.rot13("pbafhzre_xrl"), CryptUtils.rot13(cK)); + final String rotCK = CryptUtils.rot13(cK); + // check that developers are not using the Ant defined properties without any values + if (StringUtils.startsWith(rotCK, "${")) { + throw new IllegalStateException("invalid OKAPI OAuth token " + rotCK); + } + params.put(CryptUtils.rot13("pbafhzre_xrl"), rotCK); } @Override + @NonNull public String getLicenseText(final @NonNull Geocache cache) { // NOT TO BE TRANSLATED return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, " + licenseString; @@ -93,13 +99,13 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { /** * Checks if a search based on a user name targets the current user - * + * * @param username * Name of the user the query is searching after * @return True - search target and current is same, False - current user not known or not the same as username */ @SuppressWarnings("static-method") - public boolean isSearchForMyCaches(String username) { + public boolean isSearchForMyCaches(final String username) { return false; } } diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java index dd25c5e..2c783fb 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java @@ -3,7 +3,6 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.ILoggingManager; @@ -15,9 +14,10 @@ import cgeo.geocaching.connector.capability.ISearchByOwner; import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.connector.gc.MapTokens; import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.CryptUtils; @@ -50,7 +50,8 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente } @Override - public SearchResult searchByViewport(@NonNull final Viewport viewport, final MapTokens tokens) { + @NonNull + public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) { return new SearchResult(OkapiClient.getCachesBBox(viewport, this)); } @@ -99,7 +100,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente } @Override - public boolean addToWatchlist(final Geocache cache) { + public boolean addToWatchlist(@NonNull final Geocache cache) { final boolean added = OkapiClient.setWatchState(cache, true, this); if (added) { @@ -110,7 +111,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente } @Override - public boolean removeFromWatchlist(final Geocache cache) { + public boolean removeFromWatchlist(@NonNull final Geocache cache) { final boolean removed = OkapiClient.setWatchState(cache, false, this); if (removed) { @@ -126,12 +127,13 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente } @Override - public ILoggingManager getLoggingManager(final LogCacheActivity activity, final Geocache cache) { + @NonNull + public ILoggingManager getLoggingManager(@NonNull final LogCacheActivity activity, @NonNull final Geocache cache) { return new OkapiLoggingManager(activity, this, cache); } @Override - public boolean canLog(final Geocache cache) { + public boolean canLog(@NonNull final Geocache cache) { return true; } @@ -150,7 +152,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return StringUtils.isNotEmpty(getUserName()) && StringUtils.equals(cache.getOwnerDisplayName(), getUserName()); } @@ -176,8 +178,7 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente @Override public SearchResult searchByKeyword(final @NonNull String name, final @NonNull RecaptchaReceiver recaptchaReceiver) { - final Geopoint currentPos = CgeoApplication.getInstance().currentGeo().getCoords(); - return new SearchResult(OkapiClient.getCachesNamed(currentPos, name, this)); + return new SearchResult(OkapiClient.getCachesNamed(Sensors.getInstance().currentGeo().getCoords(), name, this)); } @Override diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java b/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java index a1030f0..21d10df 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java +++ b/main/src/cgeo/geocaching/connector/oc/OCAuthParams.java @@ -3,7 +3,7 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Intents; import cgeo.geocaching.R; -import cgeo.geocaching.network.OAuthAuthorizationActivity.OAuthParameters; +import cgeo.geocaching.activity.OAuthAuthorizationActivity.OAuthParameters; import org.eclipse.jdt.annotation.NonNull; diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java index eb7e7a1..c15ca6c 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java @@ -2,8 +2,8 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.Intents; import cgeo.geocaching.R; +import cgeo.geocaching.activity.OAuthAuthorizationActivity; import cgeo.geocaching.connector.oc.OkapiError.OkapiErrors; -import cgeo.geocaching.network.OAuthAuthorizationActivity; import cgeo.geocaching.settings.Settings; import ch.boye.httpclientandroidlib.HttpResponse; @@ -23,9 +23,9 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity { private int tempTokenSecretPrefKey; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { - Bundle extras = getIntent().getExtras(); + final Bundle extras = getIntent().getExtras(); if (extras != null) { titleResId = extras.getInt(Intents.EXTRA_OAUTH_TITLE_RES_ID); tokenPublicPrefKey = extras.getInt(Intents.EXTRA_OAUTH_TOKEN_PUBLIC_KEY); @@ -68,8 +68,8 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity { * Return an extended error in case of an invalid time stamp */ @Override - protected String getExtendedErrorMsg(HttpResponse response) { - OkapiError error = OkapiClient.decodeErrorResponse(response); + protected String getExtendedErrorMsg(final HttpResponse response) { + final OkapiError error = OkapiClient.decodeErrorResponse(response); if (error.getResult() == OkapiErrors.INVALID_TIMESTAMP) { return res.getString(R.string.init_login_popup_invalid_timestamp); } diff --git a/main/src/cgeo/geocaching/connector/oc/OCCZConnector.java b/main/src/cgeo/geocaching/connector/oc/OCCZConnector.java new file mode 100644 index 0000000..ee4330a --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/OCCZConnector.java @@ -0,0 +1,34 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +public class OCCZConnector extends OCConnector { + + private static final String GEOCODE_PREFIX = "OZ"; + + public OCCZConnector() { + super("OpenCaching.CZ", "www.opencaching.cz", GEOCODE_PREFIX); + } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + if (!StringUtils.containsIgnoreCase(url, "opencaching.cz")) { + return null; + } + final String id = StringUtils.substringAfter(url, "cacheid="); + try { + final String geocode = GEOCODE_PREFIX + StringUtils.leftPad(Integer.toHexString(Integer.parseInt(id)), 4, '0'); + if (canHandle(geocode)) { + return geocode; + } + } catch (final NumberFormatException e) { + Log.e("Unexpected URL for opencaching.cz " + url); + } + return super.getGeocodeFromUrl(url); + } +} diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java index 1ba88d5..6d7b23a 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java @@ -1,12 +1,13 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.R; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.enumerations.LogType; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.util.Arrays; import java.util.List; @@ -29,42 +30,46 @@ public class OCConnector extends AbstractConnector { } @Override - public boolean canHandle(@NonNull String geocode) { + public boolean canHandle(@NonNull final String geocode) { return codePattern.matcher(geocode).matches(); } @Override + @NonNull public String getName() { return name; } @Override - public String getCacheUrl(@NonNull Geocache cache) { + @NonNull + public String getCacheUrl(@NonNull final Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } @Override + @NonNull public String getHost() { return host; } @Override - public boolean isZippedGPXFile(String fileName) { + public boolean isZippedGPXFile(@NonNull final String fileName) { return GPX_ZIP_FILE_PATTERN.matcher(fileName).matches(); } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return false; } @Override + @NonNull protected String getCacheUrlPrefix() { return "http://" + host + "/viewcache.php?wp="; } @Override - public int getCacheMapMarkerId(boolean disabled) { + public int getCacheMapMarkerId(final boolean disabled) { if (disabled) { return R.drawable.marker_disabled_oc; } @@ -72,11 +77,32 @@ public class OCConnector extends AbstractConnector { } @Override - public final List<LogType> getPossibleLogTypes(Geocache cache) { + @NonNull + public final List<LogType> getPossibleLogTypes(@NonNull final Geocache cache) { if (cache.isEventCache()) { return EVENT_LOG_TYPES; } return STANDARD_LOG_TYPES; } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + // different opencaching installations have different supported URLs + + // host.tld/geocode + final String shortHost = StringUtils.remove(getHost(), "www."); + String geocode = StringUtils.substringAfter(url, shortHost + "/"); + if (canHandle(geocode)) { + return geocode; + } + + // host.tld/viewcache.php?wp=geocode + geocode = StringUtils.substringAfter(url, shortHost + "/viewcache.php?wp="); + if (canHandle(geocode)) { + return geocode; + } + return super.getGeocodeFromUrl(url); + } } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index bd87042..e7d4e6f 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -22,44 +22,57 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; +import cgeo.geocaching.network.OAuthTokens; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.HtmlUtils; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.SynchronizedDateFormat; import ch.boye.httpclientandroidlib.HttpResponse; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import android.net.Uri; +import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.EnumSet; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; - +import java.util.regex.Pattern; + +/** + * Client for the OpenCaching API (Okapi). + * + * @see <a href="http://www.opencaching.de/okapi/introduction.html">Okapi overview</a> + * + */ final class OkapiClient { + private static final String PARAMETER_LOGCOUNT_VALUE = "all"; + private static final String PARAMETER_LOGCOUNT_KEY = "lpc"; private static final char SEPARATOR = '|'; private static final String SEPARATOR_STRING = Character.toString(SEPARATOR); private static final SynchronizedDateFormat LOG_DATE_FORMAT = new SynchronizedDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("UTC"), Locale.US); @@ -132,6 +145,8 @@ final class OkapiClient { private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest"; private static final String METHOD_RETRIEVE_CACHES = "services/caches/geocaches"; + private static final Pattern PATTERN_TIMEZONE = Pattern.compile("([+-][01][0-9]):([03])0"); + public static Geocache getCache(final String geoCode) { final Parameters params = new Parameters("cache_code", geoCode); final IConnector connector = ConnectorFactory.getConnector(geoCode); @@ -143,13 +158,14 @@ final class OkapiClient { params.add("fields", getFullFields(ocapiConn)); params.add("attribution_append", "none"); + params.add(PARAMETER_LOGCOUNT_KEY, PARAMETER_LOGCOUNT_VALUE); final JSONResult result = request(ocapiConn, OkapiService.SERVICE_CACHE, params); return result.isSuccess ? parseCache(result.data) : null; } - public static List<Geocache> getCachesAround(final Geopoint center, final OCApiConnector connector) { + public static List<Geocache> getCachesAround(final Geopoint center, @NonNull final OCApiConnector connector) { final String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center); final Parameters params = new Parameters("search_method", METHOD_SEARCH_NEAREST); final Map<String, String> valueMap = new LinkedHashMap<>(); @@ -160,15 +176,15 @@ final class OkapiClient { return requestCaches(connector, params, valueMap, false); } - public static List<Geocache> getCachesByOwner(final String username, final OCApiConnector connector) { + public static List<Geocache> getCachesByOwner(final String username, @NonNull final OCApiConnector connector) { return getCachesByUser(username, connector, "owner_uuid"); } - public static List<Geocache> getCachesByFinder(final String username, final OCApiConnector connector) { + public static List<Geocache> getCachesByFinder(final String username, @NonNull final OCApiConnector connector) { return getCachesByUser(username, connector, "found_by"); } - private static List<Geocache> getCachesByUser(final String username, final OCApiConnector connector, final String userRequestParam) { + private static List<Geocache> getCachesByUser(final String username, @NonNull final OCApiConnector connector, final String userRequestParam) { final Parameters params = new Parameters("search_method", METHOD_SEARCH_ALL); final Map<String, String> valueMap = new LinkedHashMap<>(); final @Nullable @@ -181,7 +197,7 @@ final class OkapiClient { return requestCaches(connector, params, valueMap, connector.isSearchForMyCaches(username)); } - public static List<Geocache> getCachesNamed(final Geopoint center, final String namePart, final OCApiConnector connector) { + public static List<Geocache> getCachesNamed(final Geopoint center, final String namePart, @NonNull final OCApiConnector connector) { final Map<String, String> valueMap = new LinkedHashMap<>(); final Parameters params; @@ -202,17 +218,22 @@ final class OkapiClient { return requestCaches(connector, params, valueMap, false); } - private static List<Geocache> requestCaches(final OCApiConnector connector, final Parameters params, final Map<String, String> valueMap, final boolean my) { + private static List<Geocache> requestCaches(@NonNull final OCApiConnector connector, final Parameters params, final Map<String, String> valueMap, final boolean my) { // if a global type filter is set, and OKAPI does not know that type, then return an empty list instead of all caches if (Settings.getCacheType() != CacheType.ALL && StringUtils.isBlank(getFilterFromType())) { return Collections.emptyList(); } addFilterParams(valueMap, connector, my); - params.add("search_params", new JSONObject(valueMap).toString()); + try { + params.add("search_params", JsonUtils.writer.writeValueAsString(valueMap)); + } catch (final JsonProcessingException e) { + Log.e("requestCaches", e); + return Collections.emptyList(); + } addRetrieveParams(params, connector); - final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data; + final ObjectNode data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params).data; if (data == null) { return Collections.emptyList(); @@ -224,7 +245,7 @@ final class OkapiClient { /** * Assumes level 3 OAuth. */ - public static List<Geocache> getCachesBBox(final Viewport viewport, final OCApiConnector connector) { + public static List<Geocache> getCachesBBox(final Viewport viewport, @NonNull final OCApiConnector connector) { if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) { return Collections.emptyList(); @@ -241,11 +262,11 @@ final class OkapiClient { return requestCaches(connector, params, valueMap, false); } - public static boolean setWatchState(final Geocache cache, final boolean watched, final OCApiConnector connector) { + public static boolean setWatchState(final Geocache cache, final boolean watched, @NonNull final OCApiConnector connector) { final Parameters params = new Parameters("cache_code", cache.getGeocode()); params.add("watched", watched ? "true" : "false"); - final JSONObject data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data; + final ObjectNode data = request(connector, OkapiService.SERVICE_MARK_CACHE, params).data; if (data == null) { return false; @@ -256,7 +277,7 @@ final class OkapiClient { return true; } - public static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, final OCApiConnector connector) { + public static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, @NonNull final OCApiConnector connector) { final Parameters params = new Parameters("cache_code", cache.getGeocode()); params.add("logtype", logType.oc_type); params.add("comment", log); @@ -269,68 +290,58 @@ final class OkapiClient { params.add("password", logPassword); } - final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data; + final ObjectNode data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params).data; if (data == null) { return new LogResult(StatusCode.LOG_POST_ERROR, ""); } try { - if (data.getBoolean("success")) { - return new LogResult(StatusCode.NO_ERROR, data.getString("log_uuid")); + if (data.get("success").asBoolean()) { + return new LogResult(StatusCode.NO_ERROR, data.get("log_uuid").asText()); } return new LogResult(StatusCode.LOG_POST_ERROR, ""); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.postLog", e); } return new LogResult(StatusCode.LOG_POST_ERROR, ""); } - private static List<Geocache> parseCaches(final JSONObject response) { + private static List<Geocache> parseCaches(final ObjectNode response) { try { // Check for empty result - final String result = response.getString("results"); - if (StringUtils.isBlank(result) || StringUtils.equals(result, "[]")) { + final JsonNode results = response.path("results"); + if (!results.isObject()) { return Collections.emptyList(); } // Get and iterate result list - final JSONObject cachesResponse = response.getJSONObject("results"); - if (cachesResponse != null) { - final List<Geocache> caches = new ArrayList<>(cachesResponse.length()); - final Iterator<?> keys = cachesResponse.keys(); - while (keys.hasNext()) { - final Object next = keys.next(); - if (next instanceof String) { - final String key = (String) next; - final Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key)); - caches.add(cache); - } - } - return caches; + final List<Geocache> caches = new ArrayList<>(results.size()); + for (final JsonNode cache: results) { + caches.add(parseSmallCache((ObjectNode) cache)); } - } catch (final JSONException e) { + return caches; + } catch (ClassCastException | NullPointerException e) { Log.e("OkapiClient.parseCachesResult", e); } return Collections.emptyList(); } - private static Geocache parseSmallCache(final JSONObject response) { + private static Geocache parseSmallCache(final ObjectNode response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { - parseCoreCache(response, cache); - DataStore.saveCache(cache, EnumSet.of(SaveFlag.CACHE)); - } catch (final JSONException e) { + } catch (final NullPointerException e) { + // FIXME: here we may return a partially filled cache Log.e("OkapiClient.parseSmallCache", e); } return cache; } - private static Geocache parseCache(final JSONObject response) { + private static Geocache parseCache(final ObjectNode response) { final Geocache cache = new Geocache(); cache.setReliableLatLon(true); try { @@ -338,28 +349,27 @@ final class OkapiClient { parseCoreCache(response, cache); // not used: url - final JSONObject ownerObject = response.getJSONObject(CACHE_OWNER); - final String owner = parseUser(ownerObject); + final String owner = parseUser(response.get(CACHE_OWNER)); cache.setOwnerDisplayName(owner); // OpenCaching has no distinction between user id and user display name. Set the ID anyway to simplify c:geo workflows. cache.setOwnerUserId(owner); - cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS)); - cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS)); + cache.getLogCounts().put(LogType.FOUND_IT, response.get(CACHE_FOUNDS).asInt()); + cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.get(CACHE_NOTFOUNDS).asInt()); // only current Api - cache.getLogCounts().put(LogType.WILL_ATTEND, response.optInt(CACHE_WILLATTENDS)); + cache.getLogCounts().put(LogType.WILL_ATTEND, response.path(CACHE_WILLATTENDS).asInt()); - if (!response.isNull(CACHE_RATING)) { - cache.setRating((float) response.getDouble(CACHE_RATING)); + if (response.has(CACHE_RATING)) { + cache.setRating((float) response.get(CACHE_RATING).asDouble()); } - cache.setVotes(response.getInt(CACHE_VOTES)); + cache.setVotes(response.get(CACHE_VOTES).asInt()); - cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS)); + cache.setFavoritePoints(response.get(CACHE_RECOMMENDATIONS).asInt()); // not used: req_password // Prepend gc-link to description if available final StringBuilder description = new StringBuilder(500); - if (!response.isNull("gc_code")) { - final String gccode = response.getString("gc_code"); + if (response.hasNonNull("gc_code")) { + final String gccode = response.get("gc_code").asText(); description.append(CgeoApplication.getInstance().getResources() .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) .append(": <a href=\"http://coord.info/") @@ -368,71 +378,69 @@ final class OkapiClient { .append(gccode) .append("</a><br /><br />"); } - description.append(response.getString(CACHE_DESCRIPTION)); + description.append(response.get(CACHE_DESCRIPTION).asText()); cache.setDescription(description.toString()); // currently the hint is delivered as HTML (contrary to OKAPI documentation), so we can store it directly - cache.setHint(response.getString(CACHE_HINT)); + cache.setHint(response.get(CACHE_HINT).asText()); // not used: hints - final JSONArray images = response.getJSONArray(CACHE_IMAGES); + final ArrayNode images = (ArrayNode) response.get(CACHE_IMAGES); if (images != null) { - for (int i = 0; i < images.length(); i++) { - final JSONObject imageResponse = images.getJSONObject(i); - final String title = imageResponse.getString(CACHE_IMAGE_CAPTION); - final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode()); + for (final JsonNode imageResponse: images) { + final String title = imageResponse.get(CACHE_IMAGE_CAPTION).asText(); + final String url = absoluteUrl(imageResponse.get(CACHE_IMAGE_URL).asText(), cache.getGeocode()); // all images are added as spoiler images, although OKAPI has spoiler and non spoiler images cache.addSpoiler(new Image(url, title)); } } - cache.setAttributes(parseAttributes(response.getJSONArray(CACHE_ATTRNAMES), response.optJSONArray(CACHE_ATTR_ACODES))); + cache.setAttributes(parseAttributes((ArrayNode) response.path(CACHE_ATTRNAMES), (ArrayNode) response.get(CACHE_ATTR_ACODES))); //TODO: Store license per cache //cache.setLicense(response.getString("attribution_note")); - cache.setWaypoints(parseWaypoints(response.getJSONArray(CACHE_WPTS)), false); + cache.setWaypoints(parseWaypoints((ArrayNode) response.path(CACHE_WPTS)), false); - cache.setInventory(parseTrackables(response.getJSONArray(CACHE_TRACKABLES))); + cache.setInventory(parseTrackables((ArrayNode) response.path(CACHE_TRACKABLES))); - if (!response.isNull(CACHE_IS_WATCHED)) { - cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED)); + if (response.has(CACHE_IS_WATCHED)) { + cache.setOnWatchlist(response.get(CACHE_IS_WATCHED).asBoolean()); } - if (!response.isNull(CACHE_MY_NOTES)) { - cache.setPersonalNote(response.getString(CACHE_MY_NOTES)); - cache.parseWaypointsFromNote(); + if (response.hasNonNull(CACHE_MY_NOTES)) { + cache.setPersonalNote(response.get(CACHE_MY_NOTES).asText()); } - cache.setLogPasswordRequired(response.getBoolean(CACHE_REQ_PASSWORD)); + cache.setLogPasswordRequired(response.get(CACHE_REQ_PASSWORD).asBoolean()); cache.setDetailedUpdatedNow(); // save full detailed caches DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), parseLogs(response.getJSONArray(CACHE_LATEST_LOGS))); - } catch (final JSONException e) { + DataStore.saveLogs(cache.getGeocode(), parseLogs((ArrayNode) response.path(CACHE_LATEST_LOGS))); + } catch (ClassCastException | NullPointerException e) { Log.e("OkapiClient.parseCache", e); } return cache; } - private static void parseCoreCache(final JSONObject response, final Geocache cache) throws JSONException { - cache.setGeocode(response.getString(CACHE_CODE)); - cache.setName(response.getString(CACHE_NAME)); + private static void parseCoreCache(final ObjectNode response, final Geocache cache) { + cache.setGeocode(response.get(CACHE_CODE).asText()); + cache.setName(response.get(CACHE_NAME).asText()); // not used: names - setLocation(cache, response.getString(CACHE_LOCATION)); - cache.setType(getCacheType(response.getString(CACHE_TYPE))); + setLocation(cache, response.get(CACHE_LOCATION).asText()); + cache.setType(getCacheType(response.get(CACHE_TYPE).asText())); - final String status = response.getString(CACHE_STATUS); + final String status = response.get(CACHE_STATUS).asText(); cache.setDisabled(status.equalsIgnoreCase(CACHE_STATUS_DISABLED)); cache.setArchived(status.equalsIgnoreCase(CACHE_STATUS_ARCHIVED)); cache.setSize(getCacheSize(response)); - cache.setDifficulty((float) response.getDouble(CACHE_DIFFICULTY)); - cache.setTerrain((float) response.getDouble(CACHE_TERRAIN)); + cache.setDifficulty((float) response.get(CACHE_DIFFICULTY).asDouble()); + cache.setTerrain((float) response.get(CACHE_TERRAIN).asDouble()); - cache.setInventoryItems(response.getInt(CACHE_TRACKABLES_COUNT)); + cache.setInventoryItems(response.get(CACHE_TRACKABLES_COUNT).asInt()); - if (!response.isNull(CACHE_IS_FOUND)) { - cache.setFound(response.getBoolean(CACHE_IS_FOUND)); + if (response.has(CACHE_IS_FOUND)) { + cache.setFound(response.get(CACHE_IS_FOUND).asBoolean()); } - cache.setHidden(parseDate(response.getString(CACHE_HIDDEN))); + cache.setHidden(parseDate(response.get(CACHE_HIDDEN).asText())); } private static String absoluteUrl(final String url, final String geocode) { @@ -448,38 +456,36 @@ final class OkapiClient { return url; } - private static String parseUser(final JSONObject user) throws JSONException { - return user.getString(USER_USERNAME); + private static String parseUser(final JsonNode user) { + return user.get(USER_USERNAME).asText(); } - private static List<LogEntry> parseLogs(final JSONArray logsJSON) { + private static List<LogEntry> parseLogs(final ArrayNode logsJSON) { final List<LogEntry> result = new LinkedList<>(); - for (int i = 0; i < logsJSON.length(); i++) { + for (final JsonNode logResponse: logsJSON) { try { - final JSONObject logResponse = logsJSON.getJSONObject(i); final LogEntry log = new LogEntry( - parseUser(logResponse.getJSONObject(LOG_USER)), - parseDate(logResponse.getString(LOG_DATE)).getTime(), - parseLogType(logResponse.getString(LOG_TYPE)), - logResponse.getString(LOG_COMMENT).trim()); + parseUser(logResponse.get(LOG_USER)), + parseDate(logResponse.get(LOG_DATE).asText()).getTime(), + parseLogType(logResponse.get(LOG_TYPE).asText()), + HtmlUtils.removeExtraParagraph(logResponse.get(LOG_COMMENT).asText().trim())); result.add(log); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseLogs", e); } } return result; } - private static List<Waypoint> parseWaypoints(final JSONArray wptsJson) { + private static List<Waypoint> parseWaypoints(final ArrayNode wptsJson) { List<Waypoint> result = null; - for (int i = 0; i < wptsJson.length(); i++) { + for (final JsonNode wptResponse: wptsJson) { try { - final JSONObject wptResponse = wptsJson.getJSONObject(i); - final Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME), - parseWptType(wptResponse.getString(WPT_TYPE)), + final Waypoint wpt = new Waypoint(wptResponse.get(WPT_NAME).asText(), + parseWptType(wptResponse.get(WPT_TYPE).asText()), false); - wpt.setNote(wptResponse.getString(WPT_DESCRIPTION)); - final Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION)); + wpt.setNote(wptResponse.get(WPT_DESCRIPTION).asText()); + final Geopoint pt = parseCoords(wptResponse.get(WPT_LOCATION).asText()); if (pt != null) { wpt.setCoords(pt); } @@ -488,26 +494,25 @@ final class OkapiClient { } wpt.setPrefix(wpt.getName()); result.add(wpt); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseWaypoints", e); } } return result; } - private static List<Trackable> parseTrackables(final JSONArray trackablesJson) { - if (trackablesJson.length() == 0) { + private static List<Trackable> parseTrackables(final ArrayNode trackablesJson) { + if (trackablesJson.size() == 0) { return Collections.emptyList(); } final List<Trackable> result = new ArrayList<>(); - for (int i = 0; i < trackablesJson.length(); i++) { + for (final JsonNode trackableResponse: trackablesJson) { try { - final JSONObject trackableResponse = trackablesJson.getJSONObject(i); final Trackable trk = new Trackable(); - trk.setGeocode(trackableResponse.getString(TRK_GEOCODE)); - trk.setName(trackableResponse.getString(TRK_NAME)); + trk.setGeocode(trackableResponse.get(TRK_GEOCODE).asText()); + trk.setName(trackableResponse.get(TRK_NAME).asText()); result.add(trk); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseWaypoints", e); // Don't overwrite internal state with possibly partial result return null; @@ -576,7 +581,7 @@ final class OkapiClient { } private static Date parseDate(final String date) { - final String strippedDate = date.replaceAll("\\+0([0-9]){1}\\:00", "+0$100"); + final String strippedDate = PATTERN_TIMEZONE.matcher(date).replaceAll("$1$20"); try { return ISO8601DATEFORMAT.parse(strippedDate); } catch (final ParseException e) { @@ -595,14 +600,14 @@ final class OkapiClient { return null; } - private static List<String> parseAttributes(final JSONArray nameList, final JSONArray acodeList) { + private static List<String> parseAttributes(final ArrayNode nameList, final ArrayNode acodeList) { final List<String> result = new ArrayList<>(); - for (int i = 0; i < nameList.length(); i++) { + for (int i = 0; i < nameList.size(); i++) { try { - final String name = nameList.getString(i); - final int acode = acodeList != null ? Integer.parseInt(acodeList.getString(i).substring(1)) : CacheAttribute.NO_ID; + final String name = nameList.get(i).asText(); + final int acode = acodeList != null ? Integer.parseInt(acodeList.get(i).asText().substring(1)) : CacheAttribute.NO_ID; final CacheAttribute attr = CacheAttribute.getByOcACode(acode); if (attr != null) { @@ -610,7 +615,7 @@ final class OkapiClient { } else { result.add(name); } - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.parseAttributes", e); } } @@ -624,27 +629,29 @@ final class OkapiClient { cache.setCoords(new Geopoint(latitude, longitude)); } - private static CacheSize getCacheSize(final JSONObject response) { - if (response.isNull(CACHE_SIZE2)) { + @NonNull + private static CacheSize getCacheSize(final ObjectNode response) { + if (!response.has(CACHE_SIZE2)) { return getCacheSizeDeprecated(response); } try { - final String size = response.getString(CACHE_SIZE2); + final String size = response.get(CACHE_SIZE2).asText(); return CacheSize.getById(size); - } catch (final JSONException e) { + } catch (final NullPointerException e) { Log.e("OkapiClient.getCacheSize", e); return getCacheSizeDeprecated(response); } } - private static CacheSize getCacheSizeDeprecated(final JSONObject response) { - if (response.isNull(CACHE_SIZE_DEPRECATED)) { + @NonNull + private static CacheSize getCacheSizeDeprecated(final ObjectNode response) { + if (!response.has(CACHE_SIZE_DEPRECATED)) { return CacheSize.NOT_CHOSEN; } double size = 0; try { - size = response.getDouble(CACHE_SIZE_DEPRECATED); - } catch (final JSONException e) { + size = response.get(CACHE_SIZE_DEPRECATED).asDouble(); + } catch (final NullPointerException e) { Log.e("OkapiClient.getCacheSize", e); } switch ((int) Math.round(size)) { @@ -692,12 +699,7 @@ final class OkapiClient { return CacheType.UNKNOWN; } - private static String getCoreFields(final OCApiConnector connector) { - if (connector == null) { - Log.e("OkapiClient.getCoreFields called with invalid connector"); - return StringUtils.EMPTY; - } - + private static String getCoreFields(@NonNull final OCApiConnector connector) { if (connector.getSupportedAuthLevel() == OAuthLevel.Level3) { return SERVICE_CACHE_CORE_FIELDS + SEPARATOR + SERVICE_CACHE_CORE_L3_FIELDS; } @@ -705,12 +707,7 @@ final class OkapiClient { return SERVICE_CACHE_CORE_FIELDS; } - private static String getFullFields(final OCApiConnector connector) { - if (connector == null) { - Log.e("OkapiClient.getFullFields called with invalid connector"); - return StringUtils.EMPTY; - } - + private static String getFullFields(@NonNull final OCApiConnector connector) { final StringBuilder res = new StringBuilder(500); res.append(SERVICE_CACHE_CORE_FIELDS); @@ -730,21 +727,20 @@ final class OkapiClient { } @NonNull - private static JSONResult request(final OCApiConnector connector, final OkapiService service, final Parameters params) { - if (connector == null) { - return new JSONResult(null); - } - + private static JSONResult request(@NonNull final OCApiConnector connector, final OkapiService service, final Parameters params) { final String host = connector.getHost(); if (StringUtils.isBlank(host)) { - return new JSONResult(null); + return new JSONResult("unknown OKAPI connector host"); } params.add("langpref", getPreferredLanguage()); if (connector.getSupportedAuthLevel() == OAuthLevel.Level3) { - final ImmutablePair<String, String> tokens = Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId()); - OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens.left, tokens.right, connector.getCK(), connector.getCS()); + final OAuthTokens tokens = new OAuthTokens(connector); + if (!tokens.isValid()) { + return new JSONResult("invalid oauth tokens"); + } + OAuth.signOAuth(host, service.methodName, "GET", false, params, tokens, connector.getCK(), connector.getCS()); } else { connector.addAuthentication(params); } @@ -754,14 +750,14 @@ final class OkapiClient { } private static String getPreferredLanguage() { - final String code = Locale.getDefault().getCountry(); + final String code = Locale.getDefault().getLanguage(); if (StringUtils.isNotBlank(code)) { return StringUtils.lowerCase(code) + "|en"; } return "en"; } - private static void addFilterParams(final Map<String, String> valueMap, final OCApiConnector connector, final boolean my) { + private static void addFilterParams(final Map<String, String> valueMap, @NonNull final OCApiConnector connector, final boolean my) { if (!Settings.isExcludeDisabledCaches()) { valueMap.put("status", "Available|Temporarily unavailable"); } @@ -774,7 +770,7 @@ final class OkapiClient { } } - private static void addRetrieveParams(final Parameters params, final OCApiConnector connector) { + private static void addRetrieveParams(final Parameters params, @NonNull final OCApiConnector connector) { params.add("retr_method", METHOD_RETRIEVE_CACHES); params.add("retr_params", "{\"fields\": \"" + getCoreFields(connector) + "\"}"); params.add("wrap", "true"); @@ -800,7 +796,7 @@ final class OkapiClient { } public static @Nullable - String getUserUUID(final OCApiConnector connector, final String userName) { + String getUserUUID(@NonNull final OCApiConnector connector, final String userName) { final Parameters params = new Parameters("fields", USER_UUID, USER_USERNAME, userName); final JSONResult result = request(connector, OkapiService.SERVICE_USER_BY_USERNAME, params); @@ -810,16 +806,7 @@ final class OkapiClient { return null; } - final JSONObject data = result.data; - if (!data.isNull(USER_UUID)) { - try { - return data.getString(USER_UUID); - } catch (final JSONException e) { - Log.e("OkapiClient.getUserUUID - uuid", e); - } - } - - return null; + return result.data.path(USER_UUID).asText(null); } public static UserInfo getUserInfo(final OCApiLiveConnector connector) { @@ -833,31 +820,11 @@ final class OkapiClient { return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.getFromOkapiError(error.getResult())); } - final JSONObject data = result.data; - - String name = StringUtils.EMPTY; - boolean successUserName = false; - - if (!data.isNull(USER_USERNAME)) { - try { - name = data.getString(USER_USERNAME); - successUserName = true; - } catch (final JSONException e) { - Log.e("OkapiClient.getUserInfo - name", e); - } - } - - int finds = 0; - boolean successFinds = false; - - if (!data.isNull(USER_CACHES_FOUND)) { - try { - finds = data.getInt(USER_CACHES_FOUND); - successFinds = true; - } catch (final JSONException e) { - Log.e("OkapiClient.getUserInfo - finds", e); - } - } + final ObjectNode data = result.data; + final boolean successUserName = data.has(USER_USERNAME); + final String name = data.path(USER_USERNAME).asText(); + final boolean successFinds = data.has(USER_CACHES_FOUND); + final int finds = data.path(USER_CACHES_FOUND).asInt(); return new UserInfo(name, finds, successUserName && successFinds ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED); } @@ -874,7 +841,7 @@ final class OkapiClient { if (!result.isSuccess) { return new OkapiError(result.data); } - return new OkapiError(new JSONObject()); + return new OkapiError(new ObjectNode(JsonUtils.factory)); } /** @@ -884,21 +851,27 @@ final class OkapiClient { private static class JSONResult { public final boolean isSuccess; - public final JSONObject data; + public final ObjectNode data; public JSONResult(final @Nullable HttpResponse response) { - final boolean isSuccess = Network.isSuccess(response); + final boolean isRequestSuccessful = Network.isSuccess(response); final String responseData = Network.getResponseDataAlways(response); - JSONObject data = null; + ObjectNode tempData = null; if (responseData != null) { try { - data = new JSONObject(responseData); - } catch (final JSONException e) { + tempData = (ObjectNode) JsonUtils.reader.readTree(responseData); + } catch (IOException | ClassCastException e) { Log.w("JSONResult", e); } } - this.data = data; - this.isSuccess = isSuccess && data != null; + data = tempData; + isSuccess = isRequestSuccessful && tempData != null; + } + + public JSONResult(final @NonNull String errorMessage) { + isSuccess = false; + data = new ObjectNode(JsonUtils.factory); + data.putObject("error").put("developer_message", errorMessage); } } } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiError.java b/main/src/cgeo/geocaching/connector/oc/OkapiError.java index 7faf2c7..f3234f8 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiError.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiError.java @@ -2,11 +2,11 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.utils.Log; +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; /** * Handles the JSON error response from OKAPI @@ -26,7 +26,7 @@ public class OkapiError { @NonNull private final OkapiErrors state; @NonNull private final String message; - public OkapiError(@Nullable JSONObject data) { + public OkapiError(@Nullable final ObjectNode data) { // A null-response is by definition an error (some exception occurred somewhere in the flow) if (data == null) { @@ -39,10 +39,10 @@ public class OkapiError { String localmessage = null; OkapiErrors localstate = OkapiErrors.UNSPECIFIED; try { - JSONObject error = data.getJSONObject("error"); + final ObjectNode error = (ObjectNode) data.get("error"); // Check reason_stack element to look for the specific oauth problems we want to report back if (error.has("reason_stack")) { - String reason = error.getString("reason_stack"); + final String reason = error.get("reason_stack").asText(); if (StringUtils.contains(reason, "invalid_oauth_request")) { if (StringUtils.contains(reason, "invalid_timestamp")) { localstate = OkapiErrors.INVALID_TIMESTAMP; @@ -53,10 +53,10 @@ public class OkapiError { } // Check if we can extract a message as well if (error.has("developer_message")) { - localmessage = error.getString("developer_message"); + localmessage = error.get("developer_message").asText(); assert localmessage != null; // by virtue of defaultString } - } catch (JSONException ex) { + } catch (ClassCastException | NullPointerException ex) { Log.d("OkapiError: Failed to parse JSON", ex); localstate = OkapiErrors.UNSPECIFIED; } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java index 51c8a7e..76e597c 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java @@ -9,6 +9,9 @@ import cgeo.geocaching.connector.LogResult; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import android.net.Uri; import java.util.Calendar; @@ -19,7 +22,7 @@ public class OkapiLoggingManager extends AbstractLoggingManager { private final OCApiLiveConnector connector; private final Geocache cache; - private LogCacheActivity activity; + private final LogCacheActivity activity; private boolean hasLoaderError = true; public OkapiLoggingManager(final LogCacheActivity activity, final OCApiLiveConnector connector, final Geocache cache) { @@ -37,18 +40,21 @@ public class OkapiLoggingManager extends AbstractLoggingManager { } @Override - public final LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, final List<TrackableLog> trackableLogs) { + @NonNull + public final LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) { final LogResult result = OkapiClient.postLog(cache, logType, date, log, logPassword, connector); connector.login(null, null); return result; } @Override + @NonNull public final ImageResult postLogImage(final String logId, final String imageCaption, final String imageDescription, final Uri imageUri) { return new ImageResult(StatusCode.LOG_POST_ERROR, ""); } @Override + @NonNull public List<LogType> getPossibleLogTypes() { if (hasLoaderError) { return Collections.emptyList(); diff --git a/main/src/cgeo/geocaching/connector/oc/UserInfo.java b/main/src/cgeo/geocaching/connector/oc/UserInfo.java index c8b37cd..42249b0 100644 --- a/main/src/cgeo/geocaching/connector/oc/UserInfo.java +++ b/main/src/cgeo/geocaching/connector/oc/UserInfo.java @@ -15,11 +15,11 @@ public class UserInfo { public final int resId; - UserInfoStatus(int resId) { + UserInfoStatus(final int resId) { this.resId = resId; } - public static UserInfoStatus getFromOkapiError(OkapiErrors result) { + public static UserInfoStatus getFromOkapiError(final OkapiErrors result) { switch (result) { case NO_ERROR: return SUCCESSFUL; @@ -37,7 +37,7 @@ public class UserInfo { private final int finds; private final UserInfoStatus status; - UserInfo(String name, int finds, UserInfoStatus status) { + UserInfo(final String name, final int finds, final UserInfoStatus status) { this.name = name; this.finds = finds; this.status = status; diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java index 7d4cf7f..d1db301 100644 --- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java +++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java @@ -1,7 +1,6 @@ package cgeo.geocaching.connector.ox; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.connector.capability.ISearchByCenter; @@ -9,12 +8,13 @@ import cgeo.geocaching.connector.capability.ISearchByGeocode; import cgeo.geocaching.connector.capability.ISearchByKeyword; import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.connector.gc.MapTokens; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.CancellableHandler; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -30,33 +30,37 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I private static final Pattern PATTERN_GEOCODE = Pattern.compile("OX[A-Z0-9]+", Pattern.CASE_INSENSITIVE); @Override - public boolean canHandle(@NonNull String geocode) { + public boolean canHandle(@NonNull final String geocode) { return PATTERN_GEOCODE.matcher(geocode).matches(); } @Override - public String getCacheUrl(@NonNull Geocache cache) { + @NonNull + public String getCacheUrl(@NonNull final Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } @Override + @NonNull public String getName() { return "OpenCaching.com"; } @Override + @NonNull public String getHost() { return "www.opencaching.com"; } @Override - public String getLicenseText(@NonNull Geocache cache) { + @NonNull + public String getLicenseText(@NonNull final Geocache cache) { // NOT TO BE TRANSLATED return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons CC-BY-SA 3.0 License"; } @Override - public boolean isOwner(final ICache cache) { + public boolean isOwner(@NonNull final Geocache cache) { return false; } @@ -74,17 +78,19 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I } @Override - public SearchResult searchByCenter(@NonNull Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) { + public SearchResult searchByCenter(@NonNull final Geopoint center, final @NonNull RecaptchaReceiver recaptchaReceiver) { return createSearchResult(OpenCachingApi.searchByCenter(center)); } @Override + @NonNull protected String getCacheUrlPrefix() { return "http://www.opencaching.com/#!geocache/"; } @Override - public SearchResult searchByViewport(@NonNull Viewport viewport, final MapTokens tokens) { + @NonNull + public SearchResult searchByViewport(@NonNull final Viewport viewport, @NonNull final MapTokens tokens) { return createSearchResult(OpenCachingApi.searchByBoundingBox(viewport)); } @@ -98,10 +104,20 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I return createSearchResult(OpenCachingApi.searchByKeyword(name)); } - private static SearchResult createSearchResult(Collection<Geocache> caches) { + private static SearchResult createSearchResult(final Collection<Geocache> caches) { if (caches == null) { return null; } return new SearchResult(caches); } + + @Override + @Nullable + public String getGeocodeFromUrl(@NonNull final String url) { + final String geocode = StringUtils.substringAfter(url, "http://www.opencaching.com/de/#!geocache/"); + if (canHandle(geocode)) { + return geocode; + } + return super.getGeocodeFromUrl(url); + } } diff --git a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java index 7896826..25f66f4 100644 --- a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java +++ b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java @@ -29,7 +29,6 @@ public class OXGPXParser extends GPX10Parser { * The short description of OX caches contains "title by owner, type(T/D/Awesomeness)". That is a lot of * duplication. Additionally a space between type and (T/D/Awesomeness) is introduced. * - * @param cache */ private static void removeTitleFromShortDescription(final @NonNull Geocache cache) { cache.setShortDescription(StringUtils.replace(StringUtils.trim(StringUtils.substringAfterLast(cache.getShortDescription(), ",")), "(", " (")); diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java index b2afff5..a12a7fb 100644 --- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java +++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java @@ -2,10 +2,10 @@ package cgeo.geocaching.connector.ox; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; @@ -39,19 +39,19 @@ public class OpenCachingApi { return null; } - private static HttpResponse getRequest(String string, Parameters parameters) { + private static HttpResponse getRequest(final String uri, final Parameters parameters) { parameters.add("Authorization", DEV_KEY); - return Network.getRequest(string, parameters); + return Network.getRequest(uri, parameters); } private static Collection<Geocache> importCachesFromResponse(final HttpResponse response, final boolean isDetailed) { if (response == null) { return Collections.emptyList(); } - Collection<Geocache> caches; + final Collection<Geocache> caches; try { - caches = new OXGPXParser(StoredList.TEMPORARY_LIST_ID, isDetailed).parse(response.getEntity().getContent(), null); - } catch (Exception e) { + caches = new OXGPXParser(StoredList.TEMPORARY_LIST.id, isDetailed).parse(response.getEntity().getContent(), null); + } catch (final Exception e) { Log.e("Error importing from OpenCaching.com", e); return Collections.emptyList(); } @@ -81,10 +81,10 @@ public class OpenCachingApi { * Parameters to modify * @return True - query possible, False - no query, all caches excluded */ - private static boolean addTypeFilter(Parameters queryParameters) { + private static boolean addTypeFilter(final Parameters queryParameters) { boolean doQuery = true; if (Settings.getCacheType() != CacheType.ALL) { - String typeFilter; + final String typeFilter; switch (Settings.getCacheType()) { case TRADITIONAL: typeFilter = "Traditional Cache"; diff --git a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java index fb554b9..03549d1 100644 --- a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java @@ -1,5 +1,6 @@ package cgeo.geocaching.connector.trackable; +import cgeo.geocaching.Trackable; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.connector.UserAction; @@ -16,14 +17,25 @@ public abstract class AbstractTrackableConnector implements TrackableConnector { } @Override - public @Nullable - String getTrackableCodeFromUrl(@NonNull String url) { + public boolean hasTrackableUrls() { + return true; + } + + @Override + @Nullable + public String getTrackableCodeFromUrl(@NonNull final String url) { return null; } @Override - public @NonNull - List<UserAction> getUserActions() { + @NonNull + public List<UserAction> getUserActions() { return AbstractConnector.getDefaultUserActions(); } + + @Override + @NonNull + public String getUrl(@NonNull final Trackable trackable) { + throw new IllegalStateException("this trackable does not have a corresponding URL"); + } } diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java index 03052f9..6f3749c 100644 --- a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java @@ -15,17 +15,19 @@ public class GeokretyConnector extends AbstractTrackableConnector { private static final Pattern PATTERN_GK_CODE = Pattern.compile("GK[0-9A-F]{4,}"); @Override - public boolean canHandleTrackable(String geocode) { + public boolean canHandleTrackable(final String geocode) { return geocode != null && PATTERN_GK_CODE.matcher(geocode).matches(); } @Override - public String getUrl(Trackable trackable) { + @NonNull + public String getUrl(@NonNull final Trackable trackable) { return "http://geokrety.org/konkret.php?id=" + getId(trackable.getGeocode()); } @Override - public Trackable searchTrackable(String geocode, String guid, String id) { + @Nullable + public Trackable searchTrackable(final String geocode, final String guid, final String id) { final String page = Network.getResponseData(Network.getRequest("http://geokrety.org/export2.php?gkid=" + getId(geocode))); if (page == null) { return null; @@ -33,32 +35,35 @@ public class GeokretyConnector extends AbstractTrackableConnector { return GeokretyParser.parse(page); } - protected static int getId(String geocode) { + protected static int getId(final String geocode) { try { final String hex = geocode.substring(2); return Integer.parseInt(hex, 16); } catch (final NumberFormatException e) { - Log.e("Trackable.getUrl", e); + Log.e("Trackable.getId", e); } return -1; } @Override public @Nullable - String getTrackableCodeFromUrl(@NonNull String url) { + String getTrackableCodeFromUrl(@NonNull final String url) { // http://geokrety.org/konkret.php?id=38545 String id = StringUtils.substringAfterLast(url, "konkret.php?id="); if (StringUtils.isNumeric(id)) { return geocode(Integer.parseInt(id)); } + // http://geokretymap.org/38545 + id = StringUtils.substringAfterLast(url, "geokretymap.org/"); + if (StringUtils.isNumeric(id)) { + return geocode(Integer.parseInt(id)); + } return null; } /** * Get geocode from geokrety id * - * @param id - * @return */ public static String geocode(final int id) { return String.format("GK%04X", id); diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java index 0e64abd..a6e63ca 100644 --- a/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java +++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyParser.java @@ -26,7 +26,7 @@ public class GeokretyParser { geokret.setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String name) { + public void end(final String name) { trackable.setName(name); } }); @@ -34,7 +34,7 @@ public class GeokretyParser { geokret.setStartElementListener(new StartElementListener() { @Override - public void start(Attributes attributes) { + public void start(final Attributes attributes) { try { final String kretyId = attributes.getValue("id"); if (StringUtils.isNumeric(kretyId)) { @@ -73,7 +73,7 @@ public class GeokretyParser { return null; } - protected static String getType(int type) { + protected static String getType(final int type) { switch (type) { case 0: return CgeoApplication.getInstance().getString(R.string.geokret_type_traditional); diff --git a/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java b/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java new file mode 100644 index 0000000..dcd618c --- /dev/null +++ b/main/src/cgeo/geocaching/connector/trackable/SwaggieConnector.java @@ -0,0 +1,51 @@ +package cgeo.geocaching.connector.trackable; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.network.Network; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.regex.Pattern; + +public final class SwaggieConnector extends AbstractTrackableConnector { + + private static final Pattern PATTERN_SW_CODE = Pattern.compile("SW[0-9]{4}"); + + @Override + public boolean canHandleTrackable(final String geocode) { + return geocode != null && PATTERN_SW_CODE.matcher(geocode).matches(); + } + + @Override + @NonNull + public String getUrl(@NonNull final Trackable trackable) { + return getUrl(trackable.getGeocode()); + } + + @Override + @Nullable + public Trackable searchTrackable(final String geocode, final String guid, final String id) { + final String page = Network.getResponseData(Network.getRequest(getUrl(geocode))); + if (page == null) { + return null; + } + return SwaggieParser.parse(page); + } + + @Override + @Nullable + public String getTrackableCodeFromUrl(@NonNull final String url) { + final String geocode = StringUtils.upperCase(StringUtils.substringAfterLast(url, "swaggie/")); + if (canHandleTrackable(geocode)) { + return geocode; + } + return null; + } + + private static String getUrl(final String geocode) { + return "http://geocaching.com.au/swaggie/" + geocode; + } + +} diff --git a/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java b/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java new file mode 100644 index 0000000..1883056 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/trackable/SwaggieParser.java @@ -0,0 +1,55 @@ +package cgeo.geocaching.connector.trackable; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.utils.TextUtils; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.regex.Pattern; + +final class SwaggieParser { + + private SwaggieParser() { + // utility class + } + + private static final Pattern PATTERN_NAME = Pattern.compile(Pattern.quote("<h1><a") + ".*?>(.*?)<"); + private static final Pattern PATTERN_GEOCODE = Pattern.compile(Pattern.quote("'/swaggie/") + "(.*?)'"); + private static final Pattern PATTERN_DESCRIPTION = Pattern.compile(Pattern.quote("'swaggie_description'>") + "(.*?)</div"); + private static final Pattern PATTERN_OWNER = Pattern.compile(">([^<]*?)</a> released"); + + @Nullable + public static Trackable parse(@NonNull final String page) { + final Trackable trackable = new Trackable(); + final String name = TextUtils.getMatch(page, PATTERN_NAME, null); + if (StringUtils.isEmpty(name)) { + return null; + } + trackable.setName(name); + + final String geocode = TextUtils.getMatch(page, PATTERN_GEOCODE, null); + if (StringUtils.isEmpty(geocode)) { + return null; + } + trackable.setGeocode(geocode); + + final String description = StringUtils.trim(TextUtils.getMatch(page, PATTERN_DESCRIPTION, StringUtils.EMPTY)); + if (StringUtils.isEmpty(description)) { + return null; + } + trackable.setDetails(description); + + final String owner = StringUtils.trim(TextUtils.getMatch(page, PATTERN_OWNER, StringUtils.EMPTY)); + if (StringUtils.isEmpty(owner)) { + return null; + } + trackable.setOwner(owner); + + trackable.setType("Swaggie"); + + return trackable; + } + +} diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java index 6071b5f..aea60e6 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java @@ -16,16 +16,33 @@ public interface TrackableConnector { public boolean canHandleTrackable(final String geocode); - public String getUrl(final Trackable trackable); + /** + * Check whether the connector has URLs corresponding the the trackable. + * + * @return <tt>true</tt> if the connector handles URLs, <tt>false</tt> otherwise + */ + public boolean hasTrackableUrls(); + + /** + * Return the URL for a trackable. Might throw {@link IllegalStateException} if called + * on a connector which does not have URLs for trackables. This might be checked using + * {@link #hasTrackableUrls()}. + * + * @param trackable the trackable + * @return the URL corresponding to this trackable + */ + @NonNull + public String getUrl(@NonNull final Trackable trackable); public boolean isLoggable(); + @Nullable public Trackable searchTrackable(String geocode, String guid, String id); - public @Nullable - String getTrackableCodeFromUrl(final @NonNull String url); + @Nullable + public String getTrackableCodeFromUrl(final @NonNull String url); - public @NonNull - List<UserAction> getUserActions(); + @NonNull + public List<UserAction> getUserActions(); } diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java index 77848d7..665ebea 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java @@ -20,12 +20,13 @@ public class TravelBugConnector extends AbstractTrackableConnector { private final static Pattern PATTERN_TB_CODE = Pattern.compile("(TB[0-9A-Z]+)|([0-9A-Z]{6})", Pattern.CASE_INSENSITIVE); @Override - public boolean canHandleTrackable(String geocode) { + public boolean canHandleTrackable(final String geocode) { return TravelBugConnector.PATTERN_TB_CODE.matcher(geocode).matches() && !StringUtils.startsWithIgnoreCase(geocode, "GC"); } @Override - public String getUrl(Trackable trackable) { + @NonNull + public String getUrl(@NonNull final Trackable trackable) { return "http://www.geocaching.com//track/details.aspx?tracker=" + trackable.getGeocode(); } @@ -35,7 +36,8 @@ public class TravelBugConnector extends AbstractTrackableConnector { } @Override - public Trackable searchTrackable(String geocode, String guid, String id) { + @Nullable + public Trackable searchTrackable(final String geocode, final String guid, final String id) { return GCParser.searchTrackable(geocode, guid, id); } @@ -56,15 +58,15 @@ public class TravelBugConnector extends AbstractTrackableConnector { @Override public @Nullable - String getTrackableCodeFromUrl(@NonNull String url) { + String getTrackableCodeFromUrl(@NonNull final String url) { // coord.info URLs - String code = StringUtils.substringAfterLast(url, "coord.info/"); - if (code != null && canHandleTrackable(code)) { - return code; + final String code1 = StringUtils.substringAfterLast(url, "coord.info/"); + if (canHandleTrackable(code1)) { + return code1; } - code = StringUtils.substringAfterLast(url, "?tracker="); - if (code != null && canHandleTrackable(code)) { - return code; + final String code2 = StringUtils.substringAfterLast(url, "?tracker="); + if (canHandleTrackable(code2)) { + return code2; } return null; } diff --git a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java index 0295927..885df7e 100644 --- a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java @@ -2,22 +2,23 @@ package cgeo.geocaching.connector.trackable; import cgeo.geocaching.Trackable; -import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.Nullable; public class UnknownTrackableConnector extends AbstractTrackableConnector { @Override - public boolean canHandleTrackable(String geocode) { + public boolean canHandleTrackable(final String geocode) { return false; } @Override - public String getUrl(Trackable trackable) { - return StringUtils.EMPTY; + public boolean hasTrackableUrls() { + return false; } @Override - public Trackable searchTrackable(String geocode, String guid, String id) { + @Nullable + public Trackable searchTrackable(final String geocode, final String guid, final String id) { return null; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java index 1fdb0ac..770b63b 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java +++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java @@ -4,10 +4,11 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import android.util.SparseArray; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -129,19 +130,22 @@ public enum CacheAttribute { // THIS LIST IS GENERATED: don't change anything here but read // project/attributes/readme.txt + @NonNull private static final String INTERNAL_YES = "_yes"; + @NonNull private static final String INTERNAL_NO = "_no"; public static final int NO_ID = -1; public final int gcid; public final int ocacode; + @NonNull public final String rawName; public final int drawableId; public final int stringIdYes; public final int stringIdNo; - CacheAttribute(final int gcid, final int ocacode, final String rawName, + CacheAttribute(final int gcid, final int ocacode, @NonNull final String rawName, final int drawableId, final int stringIdYes, final int stringIdNo) { this.gcid = gcid; this.ocacode = ocacode; @@ -158,44 +162,45 @@ public enum CacheAttribute { * true: for positive text, false: for negative text * @return the localized text */ + @NonNull public String getL10n(final boolean enabled) { return CgeoApplication.getInstance().getResources().getString( enabled ? stringIdYes : stringIdNo); } - private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME; + @NonNull + private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME = new HashMap<>(); + @NonNull private final static SparseArray<CacheAttribute> FIND_BY_OCACODE = new SparseArray<>(); static { - final HashMap<String, CacheAttribute> mapGcRawNames = new HashMap<>(); - for (CacheAttribute attr : values()) { - mapGcRawNames.put(attr.rawName, attr); + for (final CacheAttribute attr : values()) { + FIND_BY_GCRAWNAME.put(attr.rawName, attr); if (attr.ocacode != NO_ID) { FIND_BY_OCACODE.put(attr.ocacode, attr); } } - FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames); } - public static CacheAttribute getByRawName(final String rawName) { + @Nullable + public static CacheAttribute getByRawName(@Nullable final String rawName) { return rawName != null ? FIND_BY_GCRAWNAME.get(rawName) : null; } + @Nullable public static CacheAttribute getByOcACode(final int ocAcode) { return FIND_BY_OCACODE.get(ocAcode); } - public static String trimAttributeName(String attributeName) { + @NonNull + public static String trimAttributeName(@Nullable final String attributeName) { if (null == attributeName) { return ""; } return attributeName.replace(INTERNAL_YES, "").replace(INTERNAL_NO, "").trim(); } - public static boolean isEnabled(final String attributeName) { + public static boolean isEnabled(@Nullable final String attributeName) { return !StringUtils.endsWithIgnoreCase(attributeName, INTERNAL_NO); } - public String getAttributeName(final boolean yes) { - return rawName + (yes ? INTERNAL_YES : INTERNAL_NO); - } } diff --git a/main/src/cgeo/geocaching/enumerations/CacheListType.java b/main/src/cgeo/geocaching/enumerations/CacheListType.java index 1fce282..297e1be 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheListType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheListType.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType; +import org.eclipse.jdt.annotation.NonNull; + public enum CacheListType { OFFLINE(true, CacheListLoaderType.OFFLINE), POCKET(false, CacheListLoaderType.POCKET), @@ -19,9 +21,9 @@ public enum CacheListType { */ public final boolean canSwitch; - public final CacheListLoaderType loaderType; + @NonNull public final CacheListLoaderType loaderType; - CacheListType(final boolean canSwitch, final CacheListLoaderType loaderType) { + CacheListType(final boolean canSwitch, @NonNull final CacheListLoaderType loaderType) { this.canSwitch = canSwitch; this.loaderType = loaderType; } diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java index c4e2831..10c8c9f 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheSize.java +++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java @@ -3,7 +3,9 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import java.util.Collections; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -23,6 +25,7 @@ public enum CacheSize { OTHER("Other", 8, R.string.cache_size_other, "other"), UNKNOWN("Unknown", -1, R.string.cache_size_unknown, ""); // CacheSize not init. yet + @NonNull public final String id; public final int comparable; private final int stringId; @@ -31,26 +34,26 @@ public enum CacheSize { */ private final String ocSize2; - CacheSize(final String id, final int comparable, final int stringId, final String ocSize2) { + CacheSize(@NonNull final String id, final int comparable, final int stringId, final String ocSize2) { this.id = id; this.comparable = comparable; this.stringId = stringId; this.ocSize2 = ocSize2; } - final private static Map<String, CacheSize> FIND_BY_ID; + @NonNull + final private static Map<String, CacheSize> FIND_BY_ID = new HashMap<>(); static { - final HashMap<String, CacheSize> mapping = new HashMap<>(); for (final CacheSize cs : values()) { - mapping.put(cs.id.toLowerCase(Locale.US), cs); - mapping.put(cs.ocSize2.toLowerCase(Locale.US), cs); + FIND_BY_ID.put(cs.id.toLowerCase(Locale.US), cs); + FIND_BY_ID.put(cs.ocSize2.toLowerCase(Locale.US), cs); } // add medium as additional string for Regular - mapping.put("medium", CacheSize.REGULAR); - FIND_BY_ID = Collections.unmodifiableMap(mapping); + FIND_BY_ID.put("medium", CacheSize.REGULAR); } - public static CacheSize getById(final String id) { + @NonNull + public static CacheSize getById(@Nullable final String id) { if (id == null) { return UNKNOWN; } @@ -69,10 +72,8 @@ public enum CacheSize { /** * Bad GPX files can contain the container size encoded as number. - * - * @param id - * @return */ + @NonNull private static CacheSize getByNumber(final String id) { try { final int numerical = Integer.parseInt(id); @@ -83,12 +84,13 @@ public enum CacheSize { } } } - } catch (final NumberFormatException e) { + } catch (final NumberFormatException ignored) { // ignore, as this might be a number or not } return UNKNOWN; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java index 1d190e4..a6c32d9 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheType.java @@ -1,10 +1,11 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.ICache; +import cgeo.geocaching.Geocache; import cgeo.geocaching.R; -import java.util.Collections; +import org.eclipse.jdt.annotation.NonNull; + import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -14,26 +15,26 @@ import java.util.Map; */ public enum CacheType { - TRADITIONAL("traditional", "Traditional Cache", "32bc9333-5e52-4957-b0f6-5a2c8fc7b257", R.string.traditional, R.drawable.type_traditional), - MULTI("multi", "Multi-cache", "a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74", R.string.multi, R.drawable.type_multi), - MYSTERY("mystery", "Unknown Cache", "40861821-1835-4e11-b666-8d41064d03fe", R.string.mystery, R.drawable.type_mystery), - LETTERBOX("letterbox", "Letterbox hybrid", "4bdd8fb2-d7bc-453f-a9c5-968563b15d24", R.string.letterbox, R.drawable.type_letterbox), - EVENT("event", "Event Cache", "69eb8534-b718-4b35-ae3c-a856a55b0874", R.string.event, R.drawable.type_event), - MEGA_EVENT("mega", "Mega-Event Cache", "69eb8535-b718-4b35-ae3c-a856a55b0874", R.string.mega, R.drawable.type_mega), - GIGA_EVENT("giga", "Giga-Event Cache", "51420629-5739-4945-8bdd-ccfd434c0ead", R.string.giga, R.drawable.type_giga), - EARTH("earth", "Earthcache", "c66f5cf3-9523-4549-b8dd-759cd2f18db8", R.string.earth, R.drawable.type_earth), - CITO("cito", "Cache in Trash out Event", "57150806-bc1a-42d6-9cf0-538d171a2d22", R.string.cito, R.drawable.type_cito), - WEBCAM("webcam", "Webcam Cache", "31d2ae3c-c358-4b5f-8dcd-2185bf472d3d", R.string.webcam, R.drawable.type_webcam), - VIRTUAL("virtual", "Virtual Cache", "294d4360-ac86-4c83-84dd-8113ef678d7e", R.string.virtual, R.drawable.type_virtual), - WHERIGO("wherigo", "Wherigo Cache", "0544fa55-772d-4e5c-96a9-36a51ebcf5c9", R.string.wherigo, R.drawable.type_wherigo), - LOSTANDFOUND("lostfound", "Lost and Found Event Cache", "3ea6533d-bb52-42fe-b2d2-79a3424d4728", R.string.lostfound, R.drawable.type_event), // icon missing - PROJECT_APE("ape", "Project Ape Cache", "2555690d-b2bc-4b55-b5ac-0cb704c0b768", R.string.ape, R.drawable.type_ape), - GCHQ("gchq", "Groundspeak HQ", "416f2494-dc17-4b6a-9bab-1a29dd292d8c", R.string.gchq, R.drawable.type_hq), - GPS_EXHIBIT("gps", "GPS Adventures Exhibit", "72e69af2-7986-4990-afd9-bc16cbbb4ce3", R.string.gps, R.drawable.type_event), // icon missing - BLOCK_PARTY("block", "Groundspeak Block Party", "bc2f3df2-1aab-4601-b2ff-b5091f6c02e3", R.string.block, R.drawable.type_event), // icon missing - UNKNOWN("unknown", "unknown", "", R.string.unknown, R.drawable.type_unknown), + TRADITIONAL("traditional", "Traditional Cache", "32bc9333-5e52-4957-b0f6-5a2c8fc7b257", R.string.traditional, R.drawable.type_traditional, "2"), + MULTI("multi", "Multi-cache", "a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74", R.string.multi, R.drawable.type_multi, "3"), + MYSTERY("mystery", "Unknown Cache", "40861821-1835-4e11-b666-8d41064d03fe", R.string.mystery, R.drawable.type_mystery, "8"), + LETTERBOX("letterbox", "Letterbox hybrid", "4bdd8fb2-d7bc-453f-a9c5-968563b15d24", R.string.letterbox, R.drawable.type_letterbox, "5"), + EVENT("event", "Event Cache", "69eb8534-b718-4b35-ae3c-a856a55b0874", R.string.event, R.drawable.type_event, "6"), + MEGA_EVENT("mega", "Mega-Event Cache", "69eb8535-b718-4b35-ae3c-a856a55b0874", R.string.mega, R.drawable.type_mega, "453"), + GIGA_EVENT("giga", "Giga-Event Cache", "51420629-5739-4945-8bdd-ccfd434c0ead", R.string.giga, R.drawable.type_giga, "7005"), + EARTH("earth", "Earthcache", "c66f5cf3-9523-4549-b8dd-759cd2f18db8", R.string.earth, R.drawable.type_earth, "137"), + CITO("cito", "Cache in Trash out Event", "57150806-bc1a-42d6-9cf0-538d171a2d22", R.string.cito, R.drawable.type_cito, "13"), + WEBCAM("webcam", "Webcam Cache", "31d2ae3c-c358-4b5f-8dcd-2185bf472d3d", R.string.webcam, R.drawable.type_webcam, "11"), + VIRTUAL("virtual", "Virtual Cache", "294d4360-ac86-4c83-84dd-8113ef678d7e", R.string.virtual, R.drawable.type_virtual, "4"), + WHERIGO("wherigo", "Wherigo Cache", "0544fa55-772d-4e5c-96a9-36a51ebcf5c9", R.string.wherigo, R.drawable.type_wherigo, "1858"), + LOSTANDFOUND("lostfound", "Lost and Found Event Cache", "3ea6533d-bb52-42fe-b2d2-79a3424d4728", R.string.lostfound, R.drawable.type_event, "3653"), // icon missing + PROJECT_APE("ape", "Project Ape Cache", "2555690d-b2bc-4b55-b5ac-0cb704c0b768", R.string.ape, R.drawable.type_ape, "2"), + GCHQ("gchq", "Groundspeak HQ", "416f2494-dc17-4b6a-9bab-1a29dd292d8c", R.string.gchq, R.drawable.type_hq, "3773"), + GPS_EXHIBIT("gps", "GPS Adventures Exhibit", "72e69af2-7986-4990-afd9-bc16cbbb4ce3", R.string.gps, R.drawable.type_event, "1304"), // icon missing + BLOCK_PARTY("block", "Groundspeak Block Party", "bc2f3df2-1aab-4601-b2ff-b5091f6c02e3", R.string.block, R.drawable.type_event, "4738"), // icon missing + UNKNOWN("unknown", "unknown", "", R.string.unknown, R.drawable.type_unknown, ""), /** No real cache type -> filter */ - ALL("all", "display all caches", "9a79e6ce-3344-409c-bbe9-496530baf758", R.string.all_types, R.drawable.type_unknown); + ALL("all", "display all caches", "9a79e6ce-3344-409c-bbe9-496530baf758", R.string.all_types, R.drawable.type_unknown, ""); /** * id field is used when for storing caches in the database. @@ -47,37 +48,39 @@ public enum CacheType { public final String guid; private final int stringId; public final int markerId; + @NonNull public final String wptTypeId; - CacheType(String id, String pattern, String guid, int stringId, int markerId) { + CacheType(final String id, final String pattern, final String guid, final int stringId, final int markerId, @NonNull final String wptTypeId) { this.id = id; this.pattern = pattern; this.guid = guid; this.stringId = stringId; this.markerId = markerId; + this.wptTypeId = wptTypeId; } - private final static Map<String, CacheType> FIND_BY_ID; - private final static Map<String, CacheType> FIND_BY_PATTERN; - private final static Map<String, CacheType> FIND_BY_GUID; + @NonNull + private final static Map<String, CacheType> FIND_BY_ID = new HashMap<>(); + @NonNull + private final static Map<String, CacheType> FIND_BY_PATTERN = new HashMap<>(); + @NonNull + private final static Map<String, CacheType> FIND_BY_GUID = new HashMap<>(); + static { - final HashMap<String, CacheType> mappingId = new HashMap<>(); - final HashMap<String, CacheType> mappingPattern = new HashMap<>(); - final HashMap<String, CacheType> mappingGuid = new HashMap<>(); - for (CacheType ct : values()) { - mappingId.put(ct.id, ct); - mappingPattern.put(ct.pattern.toLowerCase(Locale.US), ct); - mappingGuid.put(ct.guid, ct); + for (final CacheType ct : values()) { + FIND_BY_ID.put(ct.id, ct); + FIND_BY_PATTERN.put(ct.pattern.toLowerCase(Locale.US), ct); + FIND_BY_GUID.put(ct.guid, ct); } // Add old mystery type for GPX file compatibility. - mappingPattern.put("Mystery Cache".toLowerCase(Locale.US), MYSTERY); + FIND_BY_PATTERN.put("Mystery Cache".toLowerCase(Locale.US), MYSTERY); // This pattern briefly appeared on gc.com in 2014-08. - mappingPattern.put("Traditional Geocache".toLowerCase(Locale.US), TRADITIONAL); - - FIND_BY_ID = Collections.unmodifiableMap(mappingId); - FIND_BY_PATTERN = Collections.unmodifiableMap(mappingPattern); - FIND_BY_GUID = Collections.unmodifiableMap(mappingGuid); + FIND_BY_PATTERN.put("Traditional Geocache".toLowerCase(Locale.US), TRADITIONAL); + // map lab caches to the virtual type for the time being + FIND_BY_PATTERN.put("Lab Cache".toLowerCase(Locale.US), VIRTUAL); } + @NonNull public static CacheType getById(final String id) { final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase(Locale.US).trim()) : null; if (result == null) { @@ -86,6 +89,7 @@ public enum CacheType { return result; } + @NonNull public static CacheType getByPattern(final String pattern) { final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase(Locale.US).trim()) : null; if (result == null) { @@ -94,6 +98,7 @@ public enum CacheType { return result; } + @NonNull public static CacheType getByGuid(final String id) { final CacheType result = (id != null) ? CacheType.FIND_BY_GUID.get(id) : null; if (result == null) { @@ -102,6 +107,7 @@ public enum CacheType { return result; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } @@ -118,10 +124,9 @@ public enum CacheType { /** * Whether this type contains the given cache. * - * @param cache * @return true if this is the ALL type or if this type equals the type of the cache. */ - public boolean contains(ICache cache) { + public boolean contains(final Geocache cache) { if (cache == null) { return false; } diff --git a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java deleted file mode 100644 index 5bcaf4a..0000000 --- a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java +++ /dev/null @@ -1,48 +0,0 @@ -package cgeo.geocaching.enumerations; - -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.R; - -import java.util.EnumSet; - -/** - * Defines the strategy for the Live Map - */ -public interface LiveMapStrategy { - - public enum StrategyFlag { - LOAD_TILES, // 2x2 tiles filling the complete viewport - PARSE_TILES, // parse PNG images - SEARCH_NEARBY // searchByCoords() - } - - public enum Strategy { - FASTEST(1, EnumSet.of(StrategyFlag.LOAD_TILES), R.string.map_strategy_fastest), - FAST(2, EnumSet.of(StrategyFlag.LOAD_TILES, StrategyFlag.PARSE_TILES), R.string.map_strategy_fast), - AUTO(3, EnumSet.noneOf(StrategyFlag.class), R.string.map_strategy_auto), - DETAILED(4, EnumSet.allOf(StrategyFlag.class), R.string.map_strategy_detailed); - - public final int id; - public final EnumSet<StrategyFlag> flags; - private final int stringId; - - Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) { - this.id = id; - this.flags = flags; - this.stringId = stringId; - } - - public static Strategy getById(final int id) { - for (Strategy strategy : Strategy.values()) { - if (strategy.id == id) { - return strategy; - } - } - return AUTO; - } - - public final String getL10n() { - return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); - } - } -} diff --git a/main/src/cgeo/geocaching/enumerations/LoadFlags.java b/main/src/cgeo/geocaching/enumerations/LoadFlags.java index c781f4b..0f08690 100644 --- a/main/src/cgeo/geocaching/enumerations/LoadFlags.java +++ b/main/src/cgeo/geocaching/enumerations/LoadFlags.java @@ -1,5 +1,7 @@ package cgeo.geocaching.enumerations; +import org.eclipse.jdt.annotation.NonNull; + import java.util.EnumSet; /** @@ -22,9 +24,9 @@ public interface LoadFlags { /** Retrieve cache from CacheCache only. Do not load from DB */ public final static EnumSet<LoadFlag> LOAD_CACHE_ONLY = EnumSet.of(LoadFlag.CACHE_BEFORE); /** Retrieve cache from CacheCache first. If not found load from DB */ - public final static EnumSet<LoadFlag> LOAD_CACHE_OR_DB = EnumSet.of(LoadFlag.CACHE_BEFORE, LoadFlag.DB_MINIMAL, LoadFlag.OFFLINE_LOG); + public final static EnumSet<LoadFlag> LOAD_CACHE_OR_DB = EnumSet.of(LoadFlag.CACHE_BEFORE, LoadFlag.DB_MINIMAL, LoadFlag.OFFLINE_LOG, LoadFlag.SPOILERS); /** Retrieve cache (minimalistic information including waypoints) from DB first. If not found load from CacheCache */ - public final static EnumSet<LoadFlag> LOAD_WAYPOINTS = EnumSet.of(LoadFlag.CACHE_AFTER, LoadFlag.DB_MINIMAL, LoadFlag.WAYPOINTS, LoadFlag.OFFLINE_LOG); + public final static EnumSet<LoadFlag> LOAD_WAYPOINTS = EnumSet.of(LoadFlag.CACHE_AFTER, LoadFlag.DB_MINIMAL, LoadFlag.WAYPOINTS, LoadFlag.OFFLINE_LOG, LoadFlag.SPOILERS); /** Retrieve cache (all stored informations) from DB only. Do not load from CacheCache */ public final static EnumSet<LoadFlag> LOAD_ALL_DB_ONLY = EnumSet.range(LoadFlag.DB_MINIMAL, LoadFlag.OFFLINE_LOG); @@ -33,6 +35,7 @@ public interface LoadFlags { DB // include saving to CacheCache } + @NonNull public final static EnumSet<SaveFlag> SAVE_ALL = EnumSet.allOf(SaveFlag.class); public enum RemoveFlag { @@ -41,6 +44,7 @@ public interface LoadFlags { OWN_WAYPOINTS_ONLY_FOR_TESTING // only to be used in unit testing (as we never delete own waypoints) } + @NonNull public final static EnumSet<RemoveFlag> REMOVE_ALL = EnumSet.of(RemoveFlag.CACHE, RemoveFlag.DB); }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java index 84ab7b9..bf0d66c 100644 --- a/main/src/cgeo/geocaching/enumerations/LogType.java +++ b/main/src/cgeo/geocaching/enumerations/LogType.java @@ -3,7 +3,9 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import java.util.Collections; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -46,13 +48,16 @@ public enum LogType { UNKNOWN(0, "unknown", "", "", R.string.err_unknown, R.drawable.mark_red); // LogType not init. yet public final int id; + @Nullable public final String iconName; + @NonNull public final String type; + @NonNull public final String oc_type; private final int stringId; public final int markerId; - LogType(int id, String iconName, String type, String oc_type, int stringId, int markerId) { + LogType(final int id, @Nullable final String iconName, @NonNull final String type, @NonNull final String oc_type, final int stringId, final int markerId) { this.id = id; this.iconName = iconName; this.type = type; @@ -61,27 +66,24 @@ public enum LogType { this.markerId = markerId; } - LogType(int id, String iconName, String type, String oc_type, int stringId) { + LogType(final int id, final String iconName, final String type, final String oc_type, final int stringId) { this(id, iconName, type, oc_type, stringId, R.drawable.mark_gray); } - private final static Map<String, LogType> FIND_BY_ICONNAME; - private final static Map<String, LogType> FIND_BY_TYPE; + private final static Map<String, LogType> FIND_BY_ICONNAME = new HashMap<>(); + private final static Map<String, LogType> FIND_BY_TYPE = new HashMap<>(); static { - final HashMap<String, LogType> mappingPattern = new HashMap<>(); - final HashMap<String, LogType> mappingType = new HashMap<>(); - for (LogType lt : values()) { + for (final LogType lt : values()) { if (lt.iconName != null) { - mappingPattern.put(lt.iconName, lt); + FIND_BY_ICONNAME.put(lt.iconName, lt); } - mappingType.put(lt.type, lt); + FIND_BY_TYPE.put(lt.type, lt); } - FIND_BY_ICONNAME = Collections.unmodifiableMap(mappingPattern); - FIND_BY_TYPE = Collections.unmodifiableMap(mappingType); } + @NonNull public static LogType getById(final int id) { - for (LogType logType : values()) { + for (final LogType logType : values()) { if (logType.id == id) { return logType; } @@ -89,6 +91,7 @@ public enum LogType { return UNKNOWN; } + @NonNull public static LogType getByIconName(final String imageType) { // Special case for post reviewer note, which appears sometimes as 18.png (in individual entries) or as 68.png // (in logs counts). @@ -102,6 +105,7 @@ public enum LogType { return result; } + @NonNull public static LogType getByType(final String type) { final LogType result = type != null ? LogType.FIND_BY_TYPE.get(type.toLowerCase(Locale.US).trim()) : null; if (result == null) { @@ -110,7 +114,16 @@ public enum LogType { return result; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } + + public final boolean isFoundLog() { + return this == LogType.FOUND_IT || this == LogType.ATTENDED || this == LogType.WEBCAM_PHOTO_TAKEN; + } + + public boolean mustConfirmLog() { + return this == ARCHIVE || this == NEEDS_ARCHIVE; + } } diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java index e008294..05ce6fd 100644 --- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java +++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java @@ -3,19 +3,22 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + public enum LogTypeTrackable { DO_NOTHING("", R.string.log_tb_nothing), VISITED("_Visited", R.string.log_tb_visit), DROPPED_OFF("_DroppedOff", R.string.log_tb_drop); - final public String action; + @NonNull final public String action; final private int resourceId; - LogTypeTrackable(String action, int resourceId) { + LogTypeTrackable(@NonNull final String action, final int resourceId) { this.action = action; this.resourceId = resourceId; } + @NonNull public String getLabel() { return CgeoApplication.getInstance().getString(resourceId); } diff --git a/main/src/cgeo/geocaching/enumerations/StatusCode.java b/main/src/cgeo/geocaching/enumerations/StatusCode.java index 8bda371..37d027f 100644 --- a/main/src/cgeo/geocaching/enumerations/StatusCode.java +++ b/main/src/cgeo/geocaching/enumerations/StatusCode.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import android.content.res.Resources; public enum StatusCode { @@ -21,14 +23,13 @@ public enum StatusCode { PREMIUM_ONLY(R.string.err_premium_only), MAINTENANCE(R.string.err_maintenance), LOG_POST_ERROR(R.string.err_log_post_failed), - LOG_POST_ERROR_EC(R.string.err_log_post_failed_ec), NO_LOG_TEXT(R.string.warn_log_text_fill), NOT_LOGGED_IN(R.string.init_login_popup_failed), LOGIMAGE_POST_ERROR(R.string.err_logimage_post_failed); final private int error_string; - StatusCode(int error_string) { + StatusCode(final int error_string) { this.error_string = error_string; } @@ -36,6 +37,7 @@ public enum StatusCode { return error_string; } + @NonNull public String getErrorString(final Resources res) { return res.getString(error_string); } diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java index 1805635..d2281ef 100644 --- a/main/src/cgeo/geocaching/enumerations/WaypointType.java +++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java @@ -3,6 +3,8 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -22,11 +24,12 @@ public enum WaypointType { WAYPOINT("waypoint", R.string.wp_waypoint, R.drawable.waypoint_waypoint), ORIGINAL("original", R.string.wp_original, R.drawable.waypoint_waypoint); + @NonNull public final String id; public final int stringId; public final int markerId; - WaypointType(String id, int stringId, int markerId) { + WaypointType(@NonNull final String id, final int stringId, final int markerId) { this.id = id; this.stringId = stringId; this.markerId = markerId; @@ -36,34 +39,36 @@ public enum WaypointType { * inverse lookup of waypoint IDs<br/> * non public so that <code>null</code> handling can be handled centrally in the enum type itself */ - private static final Map<String, WaypointType> FIND_BY_ID; - public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = new HashSet<>(); + private static final Map<String, WaypointType> FIND_BY_ID = new HashMap<>(); + private static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL_TMP = new HashSet<>(); static { - final HashMap<String, WaypointType> mapping = new HashMap<>(); - for (WaypointType wt : values()) { - mapping.put(wt.id, wt); + for (final WaypointType wt : values()) { + FIND_BY_ID.put(wt.id, wt); if (wt != WaypointType.OWN && wt != WaypointType.ORIGINAL) { - ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL.add(wt); + ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL_TMP.add(wt); } } - FIND_BY_ID = Collections.unmodifiableMap(mapping); } + @NonNull + public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = Collections.unmodifiableSet(ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL_TMP); /** * inverse lookup of waypoint IDs<br/> * here the <code>null</code> handling shall be done */ + @NonNull public static WaypointType findById(final String id) { if (null == id) { return WAYPOINT; } - WaypointType waypointType = FIND_BY_ID.get(id); + final WaypointType waypointType = FIND_BY_ID.get(id); if (null == waypointType) { return WAYPOINT; } return waypointType; } + @NonNull public final String getL10n() { return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); } diff --git a/main/src/cgeo/geocaching/export/AbstractExport.java b/main/src/cgeo/geocaching/export/AbstractExport.java index 5d15ecb..94d0506 100644 --- a/main/src/cgeo/geocaching/export/AbstractExport.java +++ b/main/src/cgeo/geocaching/export/AbstractExport.java @@ -22,7 +22,7 @@ abstract class AbstractExport implements Export { * the resource id of the string * @return localized string */ - protected static String getString(int resourceId) { + protected static String getString(final int resourceId) { return CgeoApplication.getInstance().getString(resourceId); } @@ -35,7 +35,7 @@ abstract class AbstractExport implements Export { * The parameter * @return localized string */ - protected static String getString(int resourceId, Object... params) { + protected static String getString(final int resourceId, final Object... params) { return CgeoApplication.getInstance().getString(resourceId, params); } diff --git a/main/src/cgeo/geocaching/export/FieldNotes.java b/main/src/cgeo/geocaching/export/FieldNotes.java index 11d725a..fdc6210 100644 --- a/main/src/cgeo/geocaching/export/FieldNotes.java +++ b/main/src/cgeo/geocaching/export/FieldNotes.java @@ -41,7 +41,7 @@ class FieldNotes { return buffer.toString(); } - File writeToDirectory(File exportLocation) { + File writeToDirectory(final File exportLocation) { if (!LocalStorage.isExternalStorageAvailable()) { return null; } diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java index c03b848..c4a6adc 100644 --- a/main/src/cgeo/geocaching/export/FieldnoteExport.java +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -59,10 +59,11 @@ public class FieldnoteExport extends AbstractExport { final AlertDialog.Builder builder = new AlertDialog.Builder(activity); final Context themedContext; - if (Settings.isLightSkin() && VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) + if (Settings.isLightSkin() && VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) { themedContext = new ContextThemeWrapper(activity, R.style.dark); - else + } else { themedContext = activity; + } final View layout = View.inflate(themedContext, R.layout.fieldnote_export_dialog, null); builder.setView(layout); @@ -135,8 +136,10 @@ public class FieldnoteExport extends AbstractExport { for (final Geocache cache : caches) { if (ConnectorFactory.getConnector(cache).equals(connector) && cache.isLogOffline()) { final LogEntry log = DataStore.loadLogOffline(cache.getGeocode()); - if (!onlyNew || log.date > Settings.getFieldnoteExportDate()) { - fieldNotes.add(cache, log); + if (log != null) { + if (!onlyNew || log.date > Settings.getFieldnoteExportDate()) { + fieldNotes.add(cache, log); + } } } publishProgress(++i); diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index 61d03bc..af564da 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -98,11 +98,7 @@ public class GpxExport extends AbstractExport { } private static String[] getGeocodes(final List<Geocache> caches) { - final ArrayList<String> allGeocodes = new ArrayList<>(caches.size()); - for (final Geocache geocache : caches) { - allGeocodes.add(geocache.getGeocode()); - } - return allGeocodes.toArray(new String[allGeocodes.size()]); + return Geocache.getGeocodes(caches).toArray(new String[caches.size()]); } protected class ExportTask extends AsyncTaskWithProgress<String, File> { @@ -121,8 +117,7 @@ public class GpxExport extends AbstractExport { private File getExportFile() { final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US); - final Date now = new Date(); - return FileUtils.getUniqueNamedFile(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(now) + ".gpx"); + return FileUtils.getUniqueNamedFile(new File(Settings.getGpxExportDir(), "export_" + fileNameDateFormat.format(new Date()) + ".gpx")); } @Override @@ -156,7 +151,7 @@ public class GpxExport extends AbstractExport { if (writer != null) { try { writer.close(); - } catch (final IOException e1) { + } catch (final IOException ignored) { // Ignore double error } } diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java index b24eb4c..8139c76 100644 --- a/main/src/cgeo/geocaching/export/GpxSerializer.java +++ b/main/src/cgeo/geocaching/export/GpxSerializer.java @@ -7,7 +7,7 @@ import cgeo.geocaching.Trackable; import cgeo.geocaching.Waypoint; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.SynchronizedDateFormat; import cgeo.geocaching.utils.TextUtils; @@ -55,7 +55,7 @@ public final class GpxSerializer { } - public void writeGPX(List<String> allGeocodesIn, Writer writer, final ProgressListener progressListener) throws IOException { + public void writeGPX(final List<String> allGeocodesIn, final Writer writer, final ProgressListener progressListener) throws IOException { // create a copy of the geocode list, as we need to modify it, but it might be immutable final ArrayList<String> allGeocodes = new ArrayList<>(allGeocodesIn); @@ -88,7 +88,7 @@ public final class GpxSerializer { gpx.endDocument(); } - private void exportBatch(final XmlSerializer gpx, Collection<String> geocodesOfBatch) throws IOException { + private void exportBatch(final XmlSerializer gpx, final Collection<String> geocodesOfBatch) throws IOException { final Set<Geocache> caches = DataStore.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY); for (final Geocache cache : caches) { if (cache == null) { @@ -174,11 +174,10 @@ public final class GpxSerializer { } /** - * @param boolFlag * @return XML schema compliant boolean representation of the boolean flag. This must be either true, false, 0 or 1, * but no other value (also not upper case True/False). */ - private static String gpxBoolean(boolean boolFlag) { + private static String gpxBoolean(final boolean boolFlag) { return boolFlag ? "true" : "false"; } @@ -195,7 +194,7 @@ public final class GpxSerializer { try { final int numericPrefix = Integer.parseInt(prefix); maxPrefix = Math.max(numericPrefix, maxPrefix); - } catch (final NumberFormatException ex) { + } catch (final NumberFormatException ignored) { // ignore non numeric prefix, as it should be unique in the list of non-own waypoints already } } @@ -220,12 +219,6 @@ public final class GpxSerializer { /** * Writes one waypoint entry for cache waypoint. - * - * @param cache - * The - * @param wp - * @param prefix - * @throws IOException */ private void writeCacheWaypoint(final Waypoint wp) throws IOException { final Geopoint coords = wp.getCoords(); @@ -261,7 +254,7 @@ public final class GpxSerializer { } private void writeLogs(final Geocache cache) throws IOException { - List<LogEntry> logs = cache.getLogs(); + final List<LogEntry> logs = cache.getLogs(); if (logs.isEmpty()) { return; } @@ -297,7 +290,7 @@ public final class GpxSerializer { } private void writeTravelBugs(final Geocache cache) throws IOException { - List<Trackable> inventory = cache.getInventory(); + final List<Trackable> inventory = cache.getInventory(); if (CollectionUtils.isEmpty(inventory)) { return; } @@ -344,7 +337,7 @@ public final class GpxSerializer { return getLocationPart(cache, 0); } - private static String getLocationPart(final Geocache cache, int partIndex) { + private static String getLocationPart(final Geocache cache, final int partIndex) { final String location = cache.getLocation(); if (StringUtils.contains(location, ", ")) { final String[] parts = StringUtils.split(location, ','); @@ -356,7 +349,7 @@ public final class GpxSerializer { } public static String getCountry(final Geocache cache) { - String country = getLocationPart(cache, 1); + final String country = getLocationPart(cache, 1); if (StringUtils.isNotEmpty(country)) { return country; } diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java index 2a05cbc..3ec9849 100644 --- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java +++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java @@ -9,6 +9,7 @@ import cgeo.geocaching.utils.Log; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.ProgressDialog; import android.content.DialogInterface; @@ -38,7 +39,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext private String searchInfo; @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (msg.obj != null && waitDialog != null) { if (searchInfo == null) { searchInfo = res.getString(R.string.file_searching_in) + " "; @@ -52,7 +53,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext private String getDefaultFolders() { final ArrayList<String> names = new ArrayList<>(); - for (File dir : getExistingBaseFolders()) { + for (final File dir : getExistingBaseFolders()) { names.add(dir.getPath()); } return StringUtils.join(names, '\n'); @@ -62,7 +63,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext final private Handler loadFilesHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (waitDialog != null) { waitDialog.dismiss(); } @@ -76,17 +77,17 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext }; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(); setContentView(R.layout.gpx); - Bundle extras = getIntent().getExtras(); + final Bundle extras = getIntent().getExtras(); if (extras != null) { listId = extras.getInt(Intents.EXTRA_LIST_ID); } - if (listId <= StoredList.TEMPORARY_LIST_ID) { + if (listId <= StoredList.TEMPORARY_LIST.id) { listId = StoredList.STANDARD_LIST_ID; } @@ -100,7 +101,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext true, new DialogInterface.OnCancelListener() { @Override - public void onCancel(DialogInterface arg0) { + public void onCancel(final DialogInterface arg0) { if (searchingThread != null && searchingThread.isAlive()) { searchingThread.notifyEnd(); } @@ -171,7 +172,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext } else { Log.w("No external media mounted."); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("AbstractFileListActivity.loadFiles.run", e); } @@ -181,7 +182,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext Collections.sort(files, new Comparator<File>() { @Override - public int compare(File lhs, File rhs) { + public int compare(final File lhs, final File rhs) { return lhs.getName().compareToIgnoreCase(rhs.getName()); } }); @@ -189,7 +190,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext loadFilesHandler.sendMessage(Message.obtain(loadFilesHandler)); } - private void listDirs(List<File> list, List<File> directories, FileListSelector selector, Handler feedbackHandler) { + private void listDirs(final List<File> list, final List<File> directories, final FileListSelector selector, final Handler feedbackHandler) { for (final File dir : directories) { FileUtils.listDir(list, dir, selector, feedbackHandler); } @@ -200,11 +201,10 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext * Check if a filename belongs to the AbstractFileListActivity. This implementation checks for file extensions. * Subclasses may override this method to filter out specific files. * - * @param filename * @return <code>true</code> if the filename belongs to the list */ - protected boolean filenameBelongsToList(final String filename) { - for (String ext : extensions) { + protected boolean filenameBelongsToList(@NonNull final String filename) { + for (final String ext : extensions) { if (StringUtils.endsWithIgnoreCase(filename, ext)) { return true; } @@ -213,7 +213,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext } protected List<File> getExistingBaseFolders() { - ArrayList<File> result = new ArrayList<>(); + final ArrayList<File> result = new ArrayList<>(); for (final File dir : getBaseFolders()) { if (dir.exists() && dir.isDirectory()) { result.add(dir); @@ -245,7 +245,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext boolean shouldEnd = false; @Override - public boolean isSelected(File file) { + public boolean isSelected(final File file) { return filenameBelongsToList(file.getName()); } @@ -254,7 +254,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext return shouldEnd; } - public synchronized void setShouldEnd(boolean shouldEnd) { + public synchronized void setShouldEnd(final boolean shouldEnd) { this.shouldEnd = shouldEnd; } } diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java index 973e65f..9c70a0d 100644 --- a/main/src/cgeo/geocaching/files/FileParser.java +++ b/main/src/cgeo/geocaching/files/FileParser.java @@ -4,6 +4,7 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.utils.CancellableHandler; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.CharEncoding; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -15,7 +16,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Collection; -import java.util.Date; import java.util.concurrent.CancellationException; public abstract class FileParser { @@ -23,27 +23,24 @@ public abstract class FileParser { * Parses caches from input stream. * * @param stream + * the input stream * @param progressHandler - * for reporting parsing progress (in bytes read from input stream) + * for reporting parsing progress (in bytes read from input stream) * @return collection of caches * @throws IOException - * if the input stream can't be read + * if the input stream can't be read * @throws ParserException - * if the input stream contains data not matching the file format of the parser + * if the input stream contains data not matching the file format of the parser */ + @NonNull public abstract Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException; /** * Convenience method for parsing a file. - * - * @param file - * @param progressHandler - * @return - * @throws IOException - * @throws ParserException */ + @NonNull public Collection<Geocache> parse(final File file, final CancellableHandler progressHandler) throws IOException, ParserException { - BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file)); + final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file)); try { return parse(stream, progressHandler); } finally { @@ -51,10 +48,11 @@ public abstract class FileParser { } } + @NonNull protected static StringBuilder readStream(@NonNull final InputStream is, @Nullable final CancellableHandler progressHandler) throws IOException { final StringBuilder buffer = new StringBuilder(); - ProgressInputStream progressInputStream = new ProgressInputStream(is); - final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream, "UTF-8")); + final ProgressInputStream progressInputStream = new ProgressInputStream(is); + final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream, CharEncoding.UTF_8)); try { String line; @@ -77,13 +75,13 @@ public abstract class FileParser { } } - protected static void fixCache(Geocache cache) { + protected static void fixCache(final Geocache cache) { if (cache.getInventory() != null) { cache.setInventoryItems(cache.getInventory().size()); } else { cache.setInventoryItems(0); } - final long time = new Date().getTime(); + final long time = System.currentTimeMillis(); cache.setUpdated(time); cache.setDetailedUpdate(time); } diff --git a/main/src/cgeo/geocaching/files/FileTypeDetector.java b/main/src/cgeo/geocaching/files/FileTypeDetector.java index 389b83a..d1a1892 100644 --- a/main/src/cgeo/geocaching/files/FileTypeDetector.java +++ b/main/src/cgeo/geocaching/files/FileTypeDetector.java @@ -3,6 +3,7 @@ package cgeo.geocaching.files; import cgeo.geocaching.utils.Log; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; @@ -10,7 +11,6 @@ import android.content.ContentResolver; import android.net.Uri; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -20,7 +20,7 @@ public class FileTypeDetector { private final ContentResolver contentResolver; private final Uri uri; - public FileTypeDetector(Uri uri, ContentResolver contentResolver) { + public FileTypeDetector(final Uri uri, final ContentResolver contentResolver) { this.uri = uri; this.contentResolver = contentResolver; } @@ -34,12 +34,10 @@ public class FileTypeDetector { if (is == null) { return FileType.UNKNOWN; } - reader = new BufferedReader(new InputStreamReader(is)); + reader = new BufferedReader(new InputStreamReader(is, CharEncoding.UTF_8)); type = detectHeader(reader); reader.close(); - } catch (FileNotFoundException e) { - Log.e("FileTypeDetector", e); - } catch (IOException e) { + } catch (final IOException e) { Log.e("FileTypeDetector", e); } finally { IOUtils.closeQuietly(reader); @@ -48,7 +46,7 @@ public class FileTypeDetector { return type; } - private static FileType detectHeader(BufferedReader reader) + private static FileType detectHeader(final BufferedReader reader) throws IOException { String line = reader.readLine(); if (isZip(line)) { @@ -68,7 +66,7 @@ public class FileTypeDetector { return FileType.UNKNOWN; } - private static boolean isZip(String line) { + private static boolean isZip(final String line) { return StringUtils.length(line) >= 4 && StringUtils.startsWith(line, "PK") && line.charAt(2) == 3 && line.charAt(3) == 4; diff --git a/main/src/cgeo/geocaching/files/GPX10Parser.java b/main/src/cgeo/geocaching/files/GPX10Parser.java index 0ca2606..815d577 100644 --- a/main/src/cgeo/geocaching/files/GPX10Parser.java +++ b/main/src/cgeo/geocaching/files/GPX10Parser.java @@ -4,12 +4,12 @@ import android.sax.Element; public class GPX10Parser extends GPXParser { - public GPX10Parser(int listIdIn) { + public GPX10Parser(final int listIdIn) { super(listIdIn, "http://www.topografix.com/GPX/1/0", "1.0"); } @Override - protected Element getCacheParent(Element waypoint) { + protected Element getCacheParent(final Element waypoint) { return waypoint; } diff --git a/main/src/cgeo/geocaching/files/GPX11Parser.java b/main/src/cgeo/geocaching/files/GPX11Parser.java index 52a6ae3..6ac152c 100644 --- a/main/src/cgeo/geocaching/files/GPX11Parser.java +++ b/main/src/cgeo/geocaching/files/GPX11Parser.java @@ -4,12 +4,12 @@ import android.sax.Element; public final class GPX11Parser extends GPXParser { - public GPX11Parser(int listIdIn) { + public GPX11Parser(final int listIdIn) { super(listIdIn, "http://www.topografix.com/GPX/1/1", "1.1"); } @Override - protected Element getCacheParent(Element waypoint) { + protected Element getCacheParent(final Element waypoint) { return waypoint.getChild(namespace, "extensions"); } diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index 52f68e1..5699ebe 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -95,8 +95,6 @@ public class GPXImporter { * * @param uri * URI of the file to import - * @param mimeType - * @param pathName */ public void importGPX(final Uri uri, final @Nullable String mimeType, final @Nullable String pathName) { final ContentResolver contentResolver = fromActivity.getContentResolver(); @@ -113,7 +111,7 @@ public class GPXImporter { fileType = getFileTypeFromMimeType(mimeType); } - ImportThread importer = getImporterFromFileType(uri, contentResolver, + final ImportThread importer = getImporterFromFileType(uri, contentResolver, fileType); if (importer != null) { @@ -139,14 +137,15 @@ public class GPXImporter { final String mimeType) { if (GPX_MIME_TYPES.contains(mimeType)) { return FileType.GPX; - } else if (ZIP_MIME_TYPES.contains(mimeType)) { + } + if (ZIP_MIME_TYPES.contains(mimeType)) { return FileType.ZIP; } - return FileType.UNKNOWN; + return FileType.UNKNOWN; } - private ImportThread getImporterFromFileType(Uri uri, - ContentResolver contentResolver, FileType fileType) { + private ImportThread getImporterFromFileType(final Uri uri, + final ContentResolver contentResolver, final FileType fileType) { switch (fileType) { case ZIP: return new ImportGpxZipAttachmentThread(uri, contentResolver, @@ -178,7 +177,7 @@ public class GPXImporter { final Handler importStepHandler; final CancellableHandler progressHandler; - protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { + protected ImportThread(final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { this.listId = listId; this.importStepHandler = importStepHandler; this.progressHandler = progressHandler; @@ -210,7 +209,7 @@ public class GPXImporter { } catch (final ParserException e) { Log.i("Importing caches failed - data format error", e); importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage())); - } catch (final CancellationException e) { + } catch (final CancellationException ignored) { Log.i("Importing caches canceled"); importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED)); } catch (final Exception e) { @@ -244,7 +243,7 @@ public class GPXImporter { static class ImportLocFileThread extends ImportThread { private final File file; - public ImportLocFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + public ImportLocFileThread(final File file, final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); this.file = file; } @@ -262,7 +261,7 @@ public class GPXImporter { private final Uri uri; private final ContentResolver contentResolver; - public ImportLocAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + public ImportLocAttachmentThread(final Uri uri, final ContentResolver contentResolver, final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); this.uri = uri; this.contentResolver = contentResolver; @@ -284,7 +283,7 @@ public class GPXImporter { static abstract class ImportGpxThread extends ImportThread { - protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { + protected ImportGpxThread(final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); } @@ -293,7 +292,7 @@ public class GPXImporter { try { // try to parse cache file as GPX 10 return doImport(new GPX10Parser(listId)); - } catch (final ParserException pe) { + } catch (final ParserException ignored) { // didn't work -> lets try GPX11 return doImport(new GPX11Parser(listId)); } @@ -305,13 +304,13 @@ public class GPXImporter { static class ImportGpxFileThread extends ImportGpxThread { private final File cacheFile; - public ImportGpxFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + public ImportGpxFileThread(final File file, final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); this.cacheFile = file; } @Override - protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException { + protected Collection<Geocache> doImport(final GPXParser parser) throws IOException, ParserException { Log.i("Import GPX file: " + cacheFile.getAbsolutePath()); importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) cacheFile.length())); Collection<Geocache> caches = parser.parse(cacheFile, progressHandler); @@ -333,17 +332,21 @@ public class GPXImporter { private final Uri uri; private final ContentResolver contentResolver; - public ImportGpxAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + public ImportGpxAttachmentThread(final Uri uri, final ContentResolver contentResolver, final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); this.uri = uri; this.contentResolver = contentResolver; } @Override - protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException { + protected Collection<Geocache> doImport(final GPXParser parser) throws IOException, ParserException { Log.i("Import GPX from uri: " + uri); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1)); final InputStream is = contentResolver.openInputStream(uri); + int streamSize = is.available(); + if (streamSize == 0) { + streamSize = -1; + } + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, streamSize)); try { return parser.parse(is, progressHandler); } finally { @@ -354,12 +357,12 @@ public class GPXImporter { static abstract class ImportGpxZipThread extends ImportGpxThread { - protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { + protected ImportGpxZipThread(final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); } @Override - protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException { + protected Collection<Geocache> doImport(final GPXParser parser) throws IOException, ParserException { Collection<Geocache> caches = Collections.emptySet(); // can't assume that GPX file comes before waypoint file in zip -> so we need two passes // 1. parse GPX files @@ -403,7 +406,7 @@ public class GPXImporter { static class ImportGpxZipFileThread extends ImportGpxZipThread { private final File cacheFile; - public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + public ImportGpxZipFileThread(final File file, final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); this.cacheFile = file; Log.i("Import zipped GPX: " + file); @@ -419,7 +422,7 @@ public class GPXImporter { private final Uri uri; private final ContentResolver contentResolver; - public ImportGpxZipAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + public ImportGpxZipAttachmentThread(final Uri uri, final ContentResolver contentResolver, final int listId, final Handler importStepHandler, final CancellableHandler progressHandler) { super(listId, importStepHandler, progressHandler); this.uri = uri; this.contentResolver = contentResolver; @@ -434,14 +437,14 @@ public class GPXImporter { final private CancellableHandler progressHandler = new CancellableHandler() { @Override - public void handleRegularMessage(Message msg) { + public void handleRegularMessage(final Message msg) { progress.setProgress(msg.arg1); } }; final private Handler importStepHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { switch (msg.what) { case IMPORT_STEP_START: final Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL); diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index 89ee887..aed82e6 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -8,6 +8,8 @@ import cgeo.geocaching.R; import cgeo.geocaching.Trackable; import cgeo.geocaching.Waypoint; import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.connector.capability.ILogin; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; @@ -16,8 +18,8 @@ import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; @@ -120,12 +122,12 @@ public abstract class GPXParser extends FileParser { private final class UserDataListener implements EndTextElementListener { private final int index; - public UserDataListener(int index) { + public UserDataListener(final int index) { this.index = index; } @Override - public void end(String user) { + public void end(final String user) { userData[index] = validate(user); } } @@ -223,10 +225,10 @@ public abstract class GPXParser extends FileParser { return null; // id not found } // get text for string - String stringName; + final String stringName; try { stringName = CgeoApplication.getInstance().getResources().getResourceName(stringId); - } catch (final NullPointerException e) { + } catch (final NullPointerException ignored) { return null; } if (stringName == null) { @@ -250,13 +252,13 @@ public abstract class GPXParser extends FileParser { } } - protected GPXParser(int listIdIn, String namespaceIn, String versionIn) { + protected GPXParser(final int listIdIn, final String namespaceIn, final String versionIn) { listId = listIdIn; namespace = namespaceIn; version = versionIn; } - static Date parseDate(String inputUntrimmed) throws ParseException { + static Date parseDate(final String inputUntrimmed) throws ParseException { String input = inputUntrimmed.trim(); // remove milliseconds to reduce number of needed patterns final MatcherWrapper matcher = new MatcherWrapper(PATTERN_MILLISECONDS, input); @@ -272,6 +274,7 @@ public abstract class GPXParser extends FileParser { } @Override + @NonNull public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException { resetCache(); final RootElement root = new RootElement(namespace, "gpx"); @@ -280,7 +283,7 @@ public abstract class GPXParser extends FileParser { root.getChild(namespace, "url").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { scriptUrl = body; } }); @@ -289,7 +292,7 @@ public abstract class GPXParser extends FileParser { waypoint.setStartElementListener(new StartElementListener() { @Override - public void start(Attributes attrs) { + public void start(final Attributes attrs) { try { if (attrs.getIndex("lat") > -1 && attrs.getIndex("lon") > -1) { final String latitude = attrs.getValue("lat"); @@ -301,7 +304,7 @@ public abstract class GPXParser extends FileParser { } } } catch (final NumberFormatException e) { - Log.w("Failed to parse waypoint's latitude and/or longitude."); + Log.w("Failed to parse waypoint's latitude and/or longitude", e); } } }); @@ -341,7 +344,7 @@ public abstract class GPXParser extends FileParser { // finally store the cache in the database result.add(geocode); DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), logs); + DataStore.saveLogs(cache.getGeocode(), logs); // avoid the cachecache using lots of memory for caches which the user did not actually look at DataStore.removeCache(geocode, EnumSet.of(RemoveFlag.CACHE)); @@ -399,7 +402,7 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "time").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { try { cache.setHidden(parseDate(body)); } catch (final Exception e) { @@ -412,7 +415,7 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "name").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { name = body; String content = body.trim(); @@ -431,7 +434,7 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "desc").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { desc = body; cache.setShortDescription(validate(body)); @@ -442,7 +445,7 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "cmt").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { cmt = body; cache.setDescription(validate(body)); @@ -453,8 +456,8 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "type").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { - final String[] content = body.split("\\|"); + public void end(final String body) { + final String[] content = StringUtils.split(body, '|'); if (content.length > 0) { type = content[0].toLowerCase(Locale.US).trim(); } @@ -477,7 +480,7 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "url").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String url) { + public void end(final String url) { final MatcherWrapper matcher = new MatcherWrapper(PATTERN_GUID, url); if (matcher.matches()) { final String guid = matcher.group(1); @@ -497,7 +500,7 @@ public abstract class GPXParser extends FileParser { waypoint.getChild(namespace, "urlname").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String urlName) { + public void end(final String urlName) { if (cache.getName().equals(cache.getGeocode()) && StringUtils.startsWith(cache.getGeocode(), "WM")) { cache.setName(StringUtils.trim(urlName)); } @@ -520,7 +523,7 @@ public abstract class GPXParser extends FileParser { gcCache.setStartElementListener(new StartElementListener() { @Override - public void start(Attributes attrs) { + public void start(final Attributes attrs) { try { if (attrs.getIndex("id") > -1) { cache.setCacheId(attrs.getValue("id")); @@ -532,7 +535,7 @@ public abstract class GPXParser extends FileParser { cache.setDisabled(!attrs.getValue("available").equalsIgnoreCase("true")); } } catch (final RuntimeException e) { - Log.w("Failed to parse cache attributes."); + Log.w("Failed to parse cache attributes", e); } } }); @@ -541,7 +544,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String cacheName) { + public void end(final String cacheName) { cache.setName(validate(cacheName)); } }); @@ -550,7 +553,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "owner").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String ownerUserId) { + public void end(final String ownerUserId) { cache.setOwnerUserId(validate(ownerUserId)); } }); @@ -559,7 +562,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "placed_by").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String ownerDisplayName) { + public void end(final String ownerDisplayName) { cache.setOwnerDisplayName(validate(ownerDisplayName)); } }); @@ -568,8 +571,13 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { - cache.setType(CacheType.getByPattern(validate(body))); + public void end(final String bodyIn) { + String body = validate(bodyIn); + // lab caches wrongly contain a prefix in the type + if (body.startsWith("Geocache|")) { + body = StringUtils.substringAfter(body, "Geocache|").trim(); + } + cache.setType(CacheType.getByPattern(body)); } }); @@ -577,7 +585,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "container").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { cache.setSize(CacheSize.getById(validate(body))); } }); @@ -597,7 +605,7 @@ public abstract class GPXParser extends FileParser { gcAttribute.setStartElementListener(new StartElementListener() { @Override - public void start(Attributes attrs) { + public void start(final Attributes attrs) { try { if (attrs.getIndex("id") > -1 && attrs.getIndex("inc") > -1) { final int attributeId = Integer.parseInt(attrs.getValue("id")); @@ -607,7 +615,7 @@ public abstract class GPXParser extends FileParser { cache.getAttributes().add(internalId); } } - } catch (final NumberFormatException e) { + } catch (final NumberFormatException ignored) { // nothing } } @@ -617,7 +625,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "difficulty").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { try { cache.setDifficulty(Float.parseFloat(body)); } catch (final NumberFormatException e) { @@ -630,7 +638,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "terrain").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { try { cache.setTerrain(Float.parseFloat(body)); } catch (final NumberFormatException e) { @@ -643,7 +651,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "country").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String country) { + public void end(final String country) { if (StringUtils.isBlank(cache.getLocation())) { cache.setLocation(validate(country)); } else { @@ -656,7 +664,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "state").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String state) { + public void end(final String state) { final String trimmedState = state.trim(); if (StringUtils.isNotEmpty(trimmedState)) { // state can be completely empty if (StringUtils.isBlank(cache.getLocation())) { @@ -672,7 +680,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "encoded_hints").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String encoded) { + public void end(final String encoded) { cache.setHint(validate(encoded)); } }); @@ -680,7 +688,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "short_description").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String shortDesc) { + public void end(final String shortDesc) { cache.setShortDescription(validate(shortDesc)); } }); @@ -688,7 +696,7 @@ public abstract class GPXParser extends FileParser { gcCache.getChild(nsGC, "long_description").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String desc) { + public void end(final String desc) { cache.setDescription(validate(desc)); } }); @@ -703,14 +711,14 @@ public abstract class GPXParser extends FileParser { gcTB.setStartElementListener(new StartElementListener() { @Override - public void start(Attributes attrs) { + public void start(final Attributes attrs) { trackable = new Trackable(); try { if (attrs.getIndex("ref") > -1) { trackable.setGeocode(attrs.getValue("ref")); } - } catch (final RuntimeException e) { + } catch (final RuntimeException ignored) { // nothing } } @@ -733,7 +741,7 @@ public abstract class GPXParser extends FileParser { gcTB.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String tbName) { + public void end(final String tbName) { trackable.setName(validate(tbName)); } }); @@ -747,14 +755,14 @@ public abstract class GPXParser extends FileParser { gcLog.setStartElementListener(new StartElementListener() { @Override - public void start(Attributes attrs) { + public void start(final Attributes attrs) { log = new LogEntry("", 0, LogType.UNKNOWN, ""); try { if (attrs.getIndex("id") > -1) { log.id = Integer.parseInt(attrs.getValue("id")); } - } catch (final NumberFormatException e) { + } catch (final NumberFormatException ignored) { // nothing } } @@ -765,6 +773,13 @@ public abstract class GPXParser extends FileParser { @Override public void end() { if (log.type != LogType.UNKNOWN) { + if (log.type.isFoundLog() && StringUtils.isNotBlank(log.author)) { + final IConnector connector = ConnectorFactory.getConnector(cache); + if (connector instanceof ILogin && StringUtils.equals(log.author, ((ILogin) connector).getUserName())) { + cache.setFound(true); + cache.setVisitedDate(log.date); + } + } logs.add(log); } } @@ -774,7 +789,7 @@ public abstract class GPXParser extends FileParser { gcLog.getChild(nsGC, "date").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { try { log.date = parseDate(body).getTime(); } catch (final Exception e) { @@ -787,7 +802,7 @@ public abstract class GPXParser extends FileParser { gcLog.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { final String logType = validate(body); log.type = LogType.getByType(logType); } @@ -797,7 +812,7 @@ public abstract class GPXParser extends FileParser { gcLog.getChild(nsGC, "finder").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String finderName) { + public void end(final String finderName) { log.author = validate(finderName); } }); @@ -806,7 +821,7 @@ public abstract class GPXParser extends FileParser { gcLog.getChild(nsGC, "text").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String logText) { + public void end(final String logText) { log.log = validate(logText); } }); @@ -814,7 +829,7 @@ public abstract class GPXParser extends FileParser { try { progressStream = new ProgressInputStream(stream); - BufferedReader reader = new BufferedReader(new InputStreamReader(progressStream, CharEncoding.UTF_8)); + final BufferedReader reader = new BufferedReader(new InputStreamReader(progressStream, CharEncoding.UTF_8)); Xml.parse(new InvalidXMLCharacterFilterReader(reader), root.getContentHandler()); return DataStore.loadCaches(result, EnumSet.of(LoadFlag.DB_MINIMAL)); } catch (final SAXException e) { @@ -825,7 +840,6 @@ public abstract class GPXParser extends FileParser { /** * Add listeners for GSAK extensions * - * @param cacheParent */ private void registerGsakExtensions(final Element cacheParent) { for (final String gsakNamespace : GSAK_NS) { @@ -833,7 +847,7 @@ public abstract class GPXParser extends FileParser { gsak.getChild(gsakNamespace, "Watch").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String watchList) { + public void end(final String watchList) { cache.setOnWatchlist(Boolean.valueOf(watchList.trim())); } }); @@ -847,7 +861,7 @@ public abstract class GPXParser extends FileParser { gsak.getChild(gsakNamespace, "Parent").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String body) { + public void end(final String body) { parentCacheCode = body; } }); @@ -855,7 +869,7 @@ public abstract class GPXParser extends FileParser { gsak.getChild(gsakNamespace, "FavPoints").setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String favoritePoints) { + public void end(final String favoritePoints) { try { cache.setFavoritePoints(Integer.parseInt(favoritePoints)); } @@ -886,7 +900,6 @@ public abstract class GPXParser extends FileParser { /** * Add listeners for c:geo extensions * - * @param cacheParent */ private void registerCgeoExtensions(final Element cacheParent) { final Element cgeoVisited = cacheParent.getChild(CGEO_NS, "visited"); @@ -894,7 +907,7 @@ public abstract class GPXParser extends FileParser { cgeoVisited.setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String visited) { + public void end(final String visited) { wptVisited = Boolean.valueOf(visited.trim()); } }); @@ -904,7 +917,7 @@ public abstract class GPXParser extends FileParser { cgeoUserDefined.setEndTextElementListener(new EndTextElementListener() { @Override - public void end(String userDefined) { + public void end(final String userDefined) { wptUserDefined = Boolean.valueOf(userDefined.trim()); } }); @@ -917,7 +930,7 @@ public abstract class GPXParser extends FileParser { * @param cache * currently imported cache */ - protected void afterParsing(Geocache cache) { + protected void afterParsing(final Geocache cache) { // can be overridden by sub classes } @@ -925,12 +938,10 @@ public abstract class GPXParser extends FileParser { * GPX 1.0 and 1.1 use different XML elements to put the cache into, therefore needs to be overwritten in the * version specific subclasses * - * @param waypoint - * @return */ protected abstract Element getCacheParent(Element waypoint); - protected static String validate(String input) { + protected static String validate(final String input) { if ("nil".equalsIgnoreCase(input)) { return ""; } diff --git a/main/src/cgeo/geocaching/files/IFileSelectionView.java b/main/src/cgeo/geocaching/files/IFileSelectionView.java index 5bbc1b2..0407ee4 100644 --- a/main/src/cgeo/geocaching/files/IFileSelectionView.java +++ b/main/src/cgeo/geocaching/files/IFileSelectionView.java @@ -8,7 +8,7 @@ public interface IFileSelectionView { String getCurrentFile(); - void setCurrentFile(String string); + void setCurrentFile(final String name); void close(); diff --git a/main/src/cgeo/geocaching/files/InvalidXMLCharacterFilterReader.java b/main/src/cgeo/geocaching/files/InvalidXMLCharacterFilterReader.java index a7a3e1b..eea14c3 100644 --- a/main/src/cgeo/geocaching/files/InvalidXMLCharacterFilterReader.java +++ b/main/src/cgeo/geocaching/files/InvalidXMLCharacterFilterReader.java @@ -1,98 +1,89 @@ -package cgeo.geocaching.files;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.io.FilterReader;
-import java.io.IOException;
-import java.io.Reader;
-
-/**
- * Filter reader which can filter out invalid XML characters and character references.
- *
- */
-public class InvalidXMLCharacterFilterReader extends FilterReader
-{
-
- public InvalidXMLCharacterFilterReader(Reader in) {
- super(in);
- }
-
- /**
- * Every overload of {@link Reader#read()} method delegates to this one so
- * it is enough to override only this one. <br />
- * To skip invalid characters this method shifts only valid chars to left
- * and returns decreased value of the original read method. So after last
- * valid character there will be some unused chars in the buffer.
- *
- * @return Number of read valid characters or <code>-1</code> if end of the
- * underling reader was reached.
- */
- @Override
- public int read(char[] cbuf, int off, int len) throws IOException {
- int read = super.read(cbuf, off, len);
- // check for end
- if (read == -1) {
- return -1;
- }
- // target position
- int pos = off - 1;
-
- int entityStart = -1;
- for (int readPos = off; readPos < off + read; readPos++) {
- boolean useChar = true;
- switch (cbuf[readPos]) {
- case '&':
- pos++;
- entityStart = readPos;
- break;
- case ';':
- pos++;
- if (entityStart >= 0) {
- int entityLength = readPos - entityStart + 1;
- if (entityLength <= 5) {
- String entity = new String(cbuf, entityStart, entityLength);
- if (StringUtils.startsWith(entity, "&#")) {
- String numberString = StringUtils.substringBetween(entity, "&#", ";");
- final int value;
- if (StringUtils.startsWith(numberString, "x")) {
- value = Integer.parseInt(numberString.substring(1), 16);
- }
- else {
- value = Integer.parseInt(numberString);
- }
- if (!isValidXMLChar((char) value)) {
- pos -= entityLength;
- useChar = false;
- }
- }
- }
- }
- break;
- default:
- if (isValidXMLChar(cbuf[readPos])) {
- pos++;
- } else {
- continue;
- }
- }
- // copy, and skip unwanted characters
- if (pos < readPos && useChar) {
- cbuf[pos] = cbuf[readPos];
- }
- }
- return pos - off + 1;
- }
-
- private static boolean isValidXMLChar(char c) {
- if ((c == 0x9) ||
- (c == 0xA) ||
- (c == 0xD) ||
- ((c >= 0x20) && (c <= 0xD7FF)) ||
- ((c >= 0xE000) && (c <= 0xFFFD)) ||
- ((c >= 0x10000) && (c <= 0x10FFFF)))
- {
- return true;
- }
- return false;
- }
+package cgeo.geocaching.files; + +import org.apache.commons.lang3.StringUtils; + +import java.io.FilterReader; +import java.io.IOException; +import java.io.Reader; + +/** + * Filter reader which can filter out invalid XML characters and character references. + * + */ +public class InvalidXMLCharacterFilterReader extends FilterReader +{ + + public InvalidXMLCharacterFilterReader(final Reader in) { + super(in); + } + + /** + * Every overload of {@link Reader#read()} method delegates to this one so + * it is enough to override only this one. <br /> + * To skip invalid characters this method shifts only valid chars to left + * and returns decreased value of the original read method. So after last + * valid character there will be some unused chars in the buffer. + * + * @return Number of read valid characters or <code>-1</code> if end of the + * underling reader was reached. + */ + @Override + public int read(final char[] cbuf, final int off, final int len) throws IOException { + final int read = super.read(cbuf, off, len); + // check for end + if (read == -1) { + return -1; + } + // target position + int pos = off - 1; + + int entityStart = -1; + for (int readPos = off; readPos < off + read; readPos++) { + boolean useChar = true; + switch (cbuf[readPos]) { + case '&': + pos++; + entityStart = readPos; + break; + case ';': + pos++; + if (entityStart >= 0) { + final int entityLength = readPos - entityStart + 1; + if (entityLength <= 5) { + final String entity = new String(cbuf, entityStart, entityLength); + if (StringUtils.startsWith(entity, "&#")) { + final String numberString = StringUtils.substringBetween(entity, "&#", ";"); + final int value; + if (StringUtils.startsWith(numberString, "x")) { + value = Integer.parseInt(numberString.substring(1), 16); + } + else { + value = Integer.parseInt(numberString); + } + if (!isValidXMLChar((char) value)) { + pos -= entityLength; + useChar = false; + } + } + } + } + break; + default: + if (isValidXMLChar(cbuf[readPos])) { + pos++; + } else { + continue; + } + } + // copy, and skip unwanted characters + if (pos < readPos && useChar) { + cbuf[pos] = cbuf[readPos]; + } + } + return pos - off + 1; + } + + private static boolean isValidXMLChar(final char c) { + return c == 0x9 || c == 0xA || c == 0xD || (c >= 0x20 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD); + } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java index 2871d77..a3d9b8a 100644 --- a/main/src/cgeo/geocaching/files/LocParser.java +++ b/main/src/cgeo/geocaching/files/LocParser.java @@ -1,43 +1,40 @@ package cgeo.geocaching.files; -import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.SearchResult; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.MatcherWrapper; +import org.apache.commons.io.Charsets; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.regex.Pattern; public final class LocParser extends FileParser { + @NonNull private static final String NAME_OWNER_SEPARATOR = " by "; - private static final Pattern patternGeocode = Pattern - .compile("name id=\"([^\"]+)\""); - private static final Pattern patternLat = Pattern - .compile("lat=\"([^\"]+)\""); - private static final Pattern patternLon = Pattern - .compile("lon=\"([^\"]+)\""); - private static final Pattern patternName = Pattern.compile("CDATA\\[([^\\]]+)\\]"); + @NonNull private static final CacheSize[] SIZES = { CacheSize.NOT_CHOSEN, // 1 CacheSize.MICRO, // 2 @@ -49,22 +46,95 @@ public final class LocParser extends FileParser { CacheSize.SMALL, // 8 }; - private int listId; + // Used so that the initial value of the geocache is not null. Never filled. + @NonNull + private static final Geocache DUMMY_GEOCACHE = new Geocache(); - public static void parseLoc(final SearchResult searchResult, final String fileContent) { - final Map<String, Geocache> cidCoords = parseCoordinates(fileContent); + private final int listId; + + public static void parseLoc(final SearchResult searchResult, final String fileContent, final Set<Geocache> caches) { + final Map<String, Geocache> cidCoords = parseLoc(fileContent); // save found cache coordinates final HashSet<String> contained = new HashSet<>(); - for (String geocode : searchResult.getGeocodes()) { + for (final String geocode : searchResult.getGeocodes()) { if (cidCoords.containsKey(geocode)) { contained.add(geocode); } } - Set<Geocache> caches = DataStore.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB); - for (Geocache cache : caches) { - Geocache coord = cidCoords.get(cache.getGeocode()); - copyCoordToCache(coord, cache); + for (final Geocache cache : caches) { + if (!cache.isReliableLatLon()) { + final Geocache coord = cidCoords.get(cache.getGeocode()); + // Archived caches will not have any coordinates + if (coord != null) { + copyCoordToCache(coord, cache); + } + } + } + } + + @NonNull + private static Map<String, Geocache> parseLoc(final String content) { + return parseLoc(new ByteArrayInputStream(content.getBytes(Charsets.UTF_8))); + } + + @NonNull + private static Map<String, Geocache> parseLoc(final InputStream content) { + try { + final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + final XmlPullParser xpp = factory.newPullParser(); + xpp.setInput(content, Charsets.UTF_8.name()); + final Map<String, Geocache> caches = new HashMap<>(); + int eventType = xpp.getEventType(); + Geocache currentCache = DUMMY_GEOCACHE; + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + switch (xpp.getName()) { + case "waypoint": + currentCache = new Geocache(); + currentCache.setType(CacheType.UNKNOWN); // Type not present in .loc file + break; + case "name": + currentCache.setGeocode(xpp.getAttributeValue(null, "id")); + if (xpp.next() == XmlPullParser.TEXT) { + final String nameOwner = xpp.getText(); + currentCache.setName(StringUtils.trim(StringUtils.substringBeforeLast(nameOwner, NAME_OWNER_SEPARATOR))); + currentCache.setOwnerUserId(StringUtils.trim(StringUtils.substringAfterLast(nameOwner, NAME_OWNER_SEPARATOR))); + } + break; + case "coord": + currentCache.setCoords(new Geopoint(Double.valueOf(xpp.getAttributeValue(null, "lat")), + Double.valueOf(xpp.getAttributeValue(null, "lon")))); + currentCache.setReliableLatLon(true); + break; + case "container": + if (xpp.next() == XmlPullParser.TEXT) { + currentCache.setSize(SIZES[Integer.parseInt(xpp.getText()) - 1]); + } + break; + case "difficulty": + if (xpp.next() == XmlPullParser.TEXT) { + currentCache.setDifficulty(Float.valueOf(xpp.getText())); + } + break; + case "terrain": + if (xpp.next() == XmlPullParser.TEXT) { + currentCache.setTerrain(Float.valueOf(xpp.getText())); + } + break; + default: + // Ignore + } + } else if (eventType == XmlPullParser.END_TAG && xpp.getName().equals("waypoint") && StringUtils.isNotBlank(currentCache.getGeocode())) { + caches.put(currentCache.getGeocode(), currentCache); + } + eventType = xpp.next(); + } + Log.d("Coordinates found in .loc content: " + caches.size()); + return caches; + } catch (XmlPullParserException | IOException e) { + Log.e("unable to parse .loc content", e); + return Collections.emptyMap(); } } @@ -81,56 +151,33 @@ public final class LocParser extends FileParser { cache.setOwnerUserId(coord.getOwnerUserId()); } - static Map<String, Geocache> parseCoordinates(final String fileContent) { - final Map<String, Geocache> coords = new HashMap<>(); - if (StringUtils.isBlank(fileContent)) { - return coords; - } - // >> premium only - - final String[] points = fileContent.split("<waypoint>"); - - // parse coordinates - for (String pointString : points) { - final Geocache pointCoord = parseCache(pointString); - if (StringUtils.isNotBlank(pointCoord.getGeocode())) { - coords.put(pointCoord.getGeocode(), pointCoord); - } - } - - Log.i("Coordinates found in .loc file: " + coords.size()); - return coords; - } - + @NonNull public static Geopoint parsePoint(final String latitude, final String longitude) { // the loc file contains the coordinates as plain floating point values, therefore avoid using the GeopointParser try { return new Geopoint(Double.valueOf(latitude), Double.valueOf(longitude)); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { Log.e("LOC format has changed", e); } // fall back to parser, just in case the format changes return new Geopoint(latitude, longitude); } - public LocParser(int listId) { + public LocParser(final int listId) { this.listId = listId; } @Override + @NonNull public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException { - final String streamContent = readStream(stream, null).toString(); - final int maxSize = streamContent.length(); - final Map<String, Geocache> coords = parseCoordinates(streamContent); + final int maxSize = stream.available(); + final Map<String, Geocache> coords = parseLoc(stream); final List<Geocache> caches = new ArrayList<>(); - for (Entry<String, Geocache> entry : coords.entrySet()) { - Geocache coord = entry.getValue(); - if (StringUtils.isBlank(coord.getGeocode()) || StringUtils.isBlank(coord.getName())) { + for (final Entry<String, Geocache> entry : coords.entrySet()) { + final Geocache cache = entry.getValue(); + if (StringUtils.isBlank(cache.getGeocode()) || StringUtils.isBlank(cache.getName())) { continue; } - Geocache cache = new Geocache(); - cache.setReliableLatLon(true); - copyCoordToCache(coord, cache); caches.add(cache); fixCache(cache); @@ -146,53 +193,4 @@ public final class LocParser extends FileParser { return caches; } - public static Geocache parseCache(final String pointString) { - final Geocache cache = new Geocache(); - final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, pointString); - if (matcherGeocode.find()) { - cache.setGeocode(matcherGeocode.group(1).trim()); - } - - final MatcherWrapper matcherName = new MatcherWrapper(patternName, pointString); - if (matcherName.find()) { - final String name = matcherName.group(1).trim(); - String ownerName = StringUtils.trim(StringUtils.substringAfterLast(name, NAME_OWNER_SEPARATOR)); - if (StringUtils.isEmpty(cache.getOwnerUserId()) && StringUtils.isNotEmpty(ownerName)) { - cache.setOwnerUserId(ownerName); - } - cache.setName(StringUtils.substringBeforeLast(name, NAME_OWNER_SEPARATOR).trim()); - } else { - cache.setName(cache.getGeocode()); - } - - final MatcherWrapper matcherLat = new MatcherWrapper(patternLat, pointString); - final MatcherWrapper matcherLon = new MatcherWrapper(patternLon, pointString); - if (matcherLat.find() && matcherLon.find()) { - cache.setCoords(parsePoint(matcherLat.group(1).trim(), matcherLon.group(1).trim())); - } - - final String difficulty = StringUtils.substringBetween(pointString, "<difficulty>", "</difficulty>"); - final String terrain = StringUtils.substringBetween(pointString, "<terrain>", "</terrain>"); - final String container = StringUtils.substringBetween(pointString, "<container>", "</container"); - try { - if (StringUtils.isNotBlank(difficulty)) { - cache.setDifficulty(Float.parseFloat(difficulty.trim())); - } - - if (StringUtils.isNotBlank(terrain)) { - cache.setTerrain(Float.parseFloat(terrain.trim())); - } - - if (StringUtils.isNotBlank(container)) { - final int size = Integer.parseInt(container.trim()); - if (size >= 1 && size <= 8) { - cache.setSize(SIZES[size - 1]); - } - } - } catch (NumberFormatException e) { - Log.e("LocParser.parseCache", e); - } - - return cache; - } } diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java index 63a1844..cfeac9a 100644 --- a/main/src/cgeo/geocaching/files/LocalStorage.java +++ b/main/src/cgeo/geocaching/files/LocalStorage.java @@ -7,7 +7,9 @@ import cgeo.geocaching.utils.Log; import ch.boye.httpclientandroidlib.Header; import ch.boye.httpclientandroidlib.HttpResponse; + import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -43,7 +45,7 @@ public final class LocalStorage { public static final String HEADER_ETAG = "etag"; /** Name of the local private directory used to hold cached information */ - public final static String cache = ".cgeo"; + public final static String CACHE_DIRNAME = ".cgeo"; private static File internalStorageBase; @@ -69,10 +71,10 @@ public final class LocalStorage { return getStorageSpecific(true); } - private static File getStorageSpecific(boolean secondary) { + private static File getStorageSpecific(final boolean secondary) { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ^ secondary ? getExternalStorageBase() : - new File(getInternalStorageBase(), LocalStorage.cache); + new File(getInternalStorageBase(), LocalStorage.CACHE_DIRNAME); } public static File getExternalDbDirectory() { @@ -84,7 +86,7 @@ public final class LocalStorage { } private static File getExternalStorageBase() { - return new File(Environment.getExternalStorageDirectory(), LocalStorage.cache); + return new File(Environment.getExternalStorageDirectory(), LocalStorage.CACHE_DIRNAME); } private static File getInternalStorageBase() { @@ -103,7 +105,7 @@ public final class LocalStorage { * @return the file extension, including the leading dot, or the empty string if none could be determined */ static String getExtension(final String url) { - String urlExt; + final String urlExt; if (url.startsWith("data:")) { // "data:image/png;base64,i53…" -> ".png" urlExt = StringUtils.substringAfter(StringUtils.substringBefore(url, ";"), "/"); @@ -122,7 +124,7 @@ public final class LocalStorage { * the geocode * @return the cache directory */ - public static File getStorageDir(@Nullable final String geocode) { + public static File getStorageDir(@NonNull final String geocode) { return storageDir(getStorage(), geocode); } @@ -134,12 +136,12 @@ public final class LocalStorage { * the geocode * @return the cache directory */ - private static File getStorageSecDir(@Nullable final String geocode) { + private static File getStorageSecDir(@NonNull final String geocode) { return storageDir(getStorageSec(), geocode); } - private static File storageDir(final File base, @Nullable final String geocode) { - return new File(base, StringUtils.defaultIfEmpty(geocode, "_others")); + private static File storageDir(final File base, @NonNull final String geocode) { + return new File(base, geocode); } /** @@ -155,7 +157,7 @@ public final class LocalStorage { * true if an url was given, false if a file name was given * @return the file */ - public static File getStorageFile(@Nullable final String geocode, final String fileNameOrUrl, final boolean isUrl, final boolean createDirs) { + public static File getStorageFile(@NonNull final String geocode, final String fileNameOrUrl, final boolean isUrl, final boolean createDirs) { return buildFile(getStorageDir(geocode), fileNameOrUrl, isUrl, createDirs); } @@ -202,7 +204,7 @@ public final class LocalStorage { saveHeader(HEADER_ETAG, saved ? response : null, targetFile); saveHeader(HEADER_LAST_MODIFIED, saved ? response : null, targetFile); return saved; - } catch (IOException e) { + } catch (final IOException e) { Log.e("LocalStorage.saveEntityToFile", e); } @@ -242,16 +244,16 @@ public final class LocalStorage { public static String getSavedHeader(final File baseFile, final String name) { try { final File file = filenameForHeader(baseFile, name); - final Reader f = new InputStreamReader(new FileInputStream(file), "UTF-8"); + final Reader reader = new InputStreamReader(new FileInputStream(file), CharEncoding.UTF_8); try { // No header will be more than 256 bytes final char[] value = new char[256]; - final int count = f.read(value); + final int count = reader.read(value); return new String(value, 0, count); } finally { - f.close(); + reader.close(); } - } catch (final FileNotFoundException e) { + } catch (final FileNotFoundException ignored) { // Do nothing, the file does not exist } catch (final Exception e) { Log.w("could not read saved header " + name + " for " + baseFile, e); @@ -291,7 +293,7 @@ public final class LocalStorage { } finally { IOUtils.closeQuietly(inputStream); } - } catch (IOException e) { + } catch (final IOException e) { Log.e("LocalStorage.saveToFile", e); FileUtils.deleteIgnoringFailure(targetFile); } @@ -321,10 +323,10 @@ public final class LocalStorage { // close here already to catch any issue with closing input.close(); output.close(); - } catch (FileNotFoundException e) { + } catch (final FileNotFoundException e) { Log.e("LocalStorage.copy: could not copy file", e); return false; - } catch (IOException e) { + } catch (final IOException e) { Log.e("LocalStorage.copy: could not copy file", e); return false; } finally { @@ -345,7 +347,7 @@ public final class LocalStorage { } // Flushing is only necessary if the stream is not immediately closed afterwards. // We rely on all callers to do that correctly outside of this method - } catch (IOException e) { + } catch (final IOException e) { Log.e("LocalStorage.copy: error when copying data", e); return false; } @@ -362,24 +364,6 @@ public final class LocalStorage { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } - public static boolean deleteDirectory(@NonNull final File dir) { - final File[] files = dir.listFiles(); - - // Although we are called on an existing directory, it might have been removed concurrently - // in the meantime, for example by the user or by another cleanup task. - if (files != null) { - for (final File file : files) { - if (file.isDirectory()) { - deleteDirectory(file); - } else { - FileUtils.delete(file); - } - } - } - - return FileUtils.delete(dir); - } - /** * Deletes all files from directory geocode with the given prefix. * @@ -398,7 +382,7 @@ public final class LocalStorage { if (!FileUtils.delete(file)) { Log.w("LocalStorage.deleteFilesPrefix: Can't delete file " + file.getName()); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("LocalStorage.deleteFilesPrefix", e); } } @@ -417,7 +401,7 @@ public final class LocalStorage { public static File[] getFilesWithPrefix(final String geocode, final String filenamePrefix) { final FilenameFilter filter = new FilenameFilter() { @Override - public boolean accept(File dir, String filename) { + public boolean accept(final File dir, final String filename) { return filename.startsWith(filenamePrefix); } }; @@ -430,35 +414,35 @@ public final class LocalStorage { */ public static List<File> getStorages() { - String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath(); - List<File> storages = new ArrayList<>(); + final String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath(); + final List<File> storages = new ArrayList<>(); storages.add(new File(extStorage)); - File file = new File(FILE_SYSTEM_TABLE_PATH); + final File file = new File(FILE_SYSTEM_TABLE_PATH); if (file.canRead()) { Reader fr = null; BufferedReader br = null; try { - fr = new InputStreamReader(new FileInputStream(file), "UTF-8"); + fr = new InputStreamReader(new FileInputStream(file), CharEncoding.UTF_8); br = new BufferedReader(fr); - String s = br.readLine(); - while (s != null) { - if (s.startsWith("dev_mount")) { - String[] tokens = StringUtils.split(s); + String str = br.readLine(); + while (str != null) { + if (str.startsWith("dev_mount")) { + final String[] tokens = StringUtils.split(str); if (tokens.length >= 3) { - String path = tokens[2]; // mountpoint + final String path = tokens[2]; // mountpoint if (!extStorage.equals(path)) { - File directory = new File(path); + final File directory = new File(path); if (directory.exists() && directory.isDirectory()) { storages.add(directory); } } } } - s = br.readLine(); + str = br.readLine(); } - } catch (IOException e) { + } catch (final IOException e) { Log.e("Could not get additional mount points for user content. " + - "Proceeding with external storage only (" + extStorage + ")"); + "Proceeding with external storage only (" + extStorage + ")", e); } finally { IOUtils.closeQuietly(fr); IOUtils.closeQuietly(br); diff --git a/main/src/cgeo/geocaching/files/NoCloseInputStream.java b/main/src/cgeo/geocaching/files/NoCloseInputStream.java index 5a72607..493f6ca 100644 --- a/main/src/cgeo/geocaching/files/NoCloseInputStream.java +++ b/main/src/cgeo/geocaching/files/NoCloseInputStream.java @@ -9,9 +9,9 @@ import java.io.InputStream; * one input stream (e.g. ZipInputStream) because SAX parser closes stream. */ public class NoCloseInputStream extends FilterInputStream { - private static ClosedInputStream closedInputStream = new ClosedInputStream(); + private static final ClosedInputStream closedInputStream = new ClosedInputStream(); - public NoCloseInputStream(InputStream in) { + public NoCloseInputStream(final InputStream in) { super(in); } diff --git a/main/src/cgeo/geocaching/files/ParserException.java b/main/src/cgeo/geocaching/files/ParserException.java index c0076cc..6c8cfda 100644 --- a/main/src/cgeo/geocaching/files/ParserException.java +++ b/main/src/cgeo/geocaching/files/ParserException.java @@ -9,11 +9,11 @@ public class ParserException extends Exception { public ParserException() { } - public ParserException(String detailMessage) { + public ParserException(final String detailMessage) { super(detailMessage); } - public ParserException(String detailMessage, Throwable throwable) { + public ParserException(final String detailMessage, final Throwable throwable) { super(detailMessage, throwable); } diff --git a/main/src/cgeo/geocaching/files/ProgressInputStream.java b/main/src/cgeo/geocaching/files/ProgressInputStream.java index 552aee0..3b249a1 100644 --- a/main/src/cgeo/geocaching/files/ProgressInputStream.java +++ b/main/src/cgeo/geocaching/files/ProgressInputStream.java @@ -16,12 +16,12 @@ public class ProgressInputStream extends FilterInputStream { private int progress = 0; - protected ProgressInputStream(InputStream in) { + protected ProgressInputStream(final InputStream in) { super(in); } @Override - public int read() throws IOException { + public int read() throws IOException { // NO_UCD This method is called from the framework final int read = super.read(); if (read >= 0) { progress++; @@ -30,7 +30,7 @@ public class ProgressInputStream extends FilterInputStream { } @Override - public int read(byte[] buffer, int offset, int count) throws IOException { + public int read(final byte[] buffer, final int offset, final int count) throws IOException { final int read = super.read(buffer, offset, count); progress += read; return read; diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java index 2aadf16..687aaa0 100644 --- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java +++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java @@ -142,7 +142,7 @@ public class SimpleDirChooser extends AbstractListActivity { for (final File currentDir : dirs) { listDirs.add(new Option(currentDir.getName(), currentDir.getAbsolutePath(), currentDir.canWrite())); } - } catch (final RuntimeException e) { + } catch (final RuntimeException ignored) { } Collections.sort(listDirs, Option.NAME_COMPARATOR); if (dir.getParent() != null) { @@ -263,7 +263,7 @@ public class SimpleDirChooser extends AbstractListActivity { private boolean checked = false; private boolean writeable = false; - private static Comparator<Option> NAME_COMPARATOR = new Comparator<SimpleDirChooser.Option>() { + private final static Comparator<Option> NAME_COMPARATOR = new Comparator<SimpleDirChooser.Option>() { @Override public int compare(final Option lhs, final Option rhs) { diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java index e602b0f..4d521c5 100644 --- a/main/src/cgeo/geocaching/filter/AbstractFilter.java +++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java @@ -1,21 +1,30 @@ package cgeo.geocaching.filter; +import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; +import org.eclipse.jdt.annotation.NonNull; + import java.util.ArrayList; import java.util.List; abstract class AbstractFilter implements IFilter { + @NonNull private final String name; - protected AbstractFilter(final String name) { + protected AbstractFilter(final int nameResourceId) { + this(CgeoApplication.getInstance().getString(nameResourceId)); + } + + protected AbstractFilter(@NonNull final String name) { this.name = name; } + @Override - public void filter(final List<Geocache> list) { + public void filter(@NonNull final List<Geocache> list) { final List<Geocache> itemsToRemove = new ArrayList<>(); - for (Geocache item : list) { + for (final Geocache item : list) { if (!accepts(item)) { itemsToRemove.add(item); } @@ -24,6 +33,7 @@ abstract class AbstractFilter implements IFilter { } @Override + @NonNull public String getName() { return name; } @@ -37,4 +47,9 @@ abstract class AbstractFilter implements IFilter { public String toString() { return getName(); } + + @Override + public int getImageId() { + return 0; + } } diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index b59ab29..6ed4a8f 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import android.content.res.Resources; import java.util.LinkedList; @@ -13,7 +15,7 @@ class AttributeFilter extends AbstractFilter { private final String attribute; - public AttributeFilter(final String name, final String attribute) { + public AttributeFilter(@NonNull final String name, final String attribute) { super(name); this.attribute = attribute; } @@ -25,13 +27,14 @@ class AttributeFilter extends AbstractFilter { } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { return cache.getAttributes().contains(attribute); } public static class Factory implements IFilterFactory { @Override + @NonNull public List<IFilter> getFilters() { final String packageName = CgeoApplication.getInstance().getBaseContext().getPackageName(); final Resources res = CgeoApplication.getInstance().getResources(); diff --git a/main/src/cgeo/geocaching/filter/DifficultyFilter.java b/main/src/cgeo/geocaching/filter/DifficultyFilter.java index 175ad75..7989560 100644 --- a/main/src/cgeo/geocaching/filter/DifficultyFilter.java +++ b/main/src/cgeo/geocaching/filter/DifficultyFilter.java @@ -3,6 +3,8 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import java.util.ArrayList; import java.util.List; @@ -13,7 +15,7 @@ class DifficultyFilter extends AbstractRangeFilter { } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { final float difficulty = cache.getDifficulty(); return rangeMin <= difficulty && difficulty < rangeMax; } @@ -24,6 +26,7 @@ class DifficultyFilter extends AbstractRangeFilter { private static final int DIFFICULTY_MAX = 5; @Override + @NonNull public List<IFilter> getFilters() { final ArrayList<IFilter> filters = new ArrayList<>(DIFFICULTY_MAX); for (int difficulty = DIFFICULTY_MIN; difficulty <= DIFFICULTY_MAX; difficulty++) { diff --git a/main/src/cgeo/geocaching/filter/DistanceFilter.java b/main/src/cgeo/geocaching/filter/DistanceFilter.java index 3328c72..b352f5d 100644 --- a/main/src/cgeo/geocaching/filter/DistanceFilter.java +++ b/main/src/cgeo/geocaching/filter/DistanceFilter.java @@ -2,28 +2,31 @@ package cgeo.geocaching.filter; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; -import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.sensors.GeoData; +import cgeo.geocaching.sensors.Sensors; + +import org.eclipse.jdt.annotation.NonNull; import java.util.ArrayList; import java.util.List; class DistanceFilter extends AbstractFilter { - private final IGeoData geo; + private final GeoData geo; private final int minDistance; private final int maxDistance; - public DistanceFilter(String name, final int minDistance, final int maxDistance) { + public DistanceFilter(@NonNull final String name, final int minDistance, final int maxDistance) { super(name); this.minDistance = minDistance; this.maxDistance = maxDistance; - geo = CgeoApplication.getInstance().currentGeo(); + geo = Sensors.getInstance().currentGeo(); } @Override - public boolean accepts(final Geocache cache) { - final Geopoint currentPos = new Geopoint(geo.getLocation()); + public boolean accepts(@NonNull final Geocache cache) { + final Geopoint currentPos = new Geopoint(geo); final Geopoint coords = cache.getCoords(); if (coords == null) { // If a cache has no coordinates, consider it to be out of range. It will @@ -39,6 +42,7 @@ class DistanceFilter extends AbstractFilter { private static final int[] KILOMETERS = { 0, 2, 5, 10, 20, 50 }; @Override + @NonNull public List<IFilter> getFilters() { final List<IFilter> filters = new ArrayList<>(KILOMETERS.length); for (int i = 0; i < KILOMETERS.length; i++) { diff --git a/main/src/cgeo/geocaching/filter/FilterActivity.java b/main/src/cgeo/geocaching/filter/FilterActivity.java new file mode 100644 index 0000000..13a2263 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/FilterActivity.java @@ -0,0 +1,154 @@ +package cgeo.geocaching.filter; + +import butterknife.ButterKnife; +import butterknife.InjectView; + +import cgeo.geocaching.R; +import cgeo.geocaching.activity.AbstractActionBarActivity; +import cgeo.geocaching.filter.FilterRegistry.FactoryEntry; +import cgeo.geocaching.utils.Log; + +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.OptionsItem; +import org.androidannotations.annotations.OptionsMenu; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.ExpandableListView; +import android.widget.ExpandableListView.OnChildClickListener; +import android.widget.LinearLayout; +import android.widget.SimpleExpandableListAdapter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Show a filter selection using an {@code ExpandableListView}. + */ +@OptionsMenu(R.menu.filter_options) +@EActivity +public class FilterActivity extends AbstractActionBarActivity { + + public static final String EXTRA_FILTER_RESULT = null; + public static final int REQUEST_SELECT_FILTER = 1234; + + private static final String KEY_FILTER_NAME = "filterName"; + private static final String KEY_FILTER_GROUP_NAME = "filterGroupName"; + + @InjectView(R.id.filterList) protected ExpandableListView filterList; + @InjectView(R.id.filters) protected LinearLayout filtersContainer; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState, R.layout.filter_activity); + ButterKnife.inject(this); + + createListAdapter(); + } + + private void createListAdapter() { + final SimpleExpandableListAdapter adapter = + new SimpleExpandableListAdapter( + this, + // top level entries in the next 4 lines + createFilterTopLevelGroups(), + android.R.layout.simple_expandable_list_item_1, + new String[] { KEY_FILTER_GROUP_NAME }, + new int[] { android.R.id.text1 }, + + // child level entries in the next 4 lines + createFilterChildren(), + android.R.layout.simple_expandable_list_item_2, + new String[] { KEY_FILTER_NAME, "CHILD_NAME" }, + new int[] { android.R.id.text1 } + ); + filterList.setAdapter(adapter); + filterList.setOnChildClickListener(new OnChildClickListener() { + + @Override + public boolean onChildClick(final ExpandableListView parent, final View v, final int groupPosition, final int childPosition, final long id) { + setFilterResult(groupPosition, childPosition); + return true; + } + + }); + } + + public static @Nullable IFilter getFilterFromPosition(final int groupPosition, final int childPosition) { + if (groupPosition < 0 || childPosition < 0) { + return null; + } + final FactoryEntry factoryEntry = FilterRegistry.getInstance().getFactories().get(groupPosition); + return createFilterFactory(factoryEntry.getFactory()).getFilters().get(childPosition); + } + + /** + * Creates the group list with the mapped properties. + */ + private static List<Map<String, String>> createFilterTopLevelGroups() { + final ArrayList<Map<String, String>> groups = new ArrayList<>(); + for (final FactoryEntry factoryEntry : FilterRegistry.getInstance().getFactories()) { + final Map<String, String> map = new HashMap<>(); + map.put(KEY_FILTER_GROUP_NAME, factoryEntry.getName()); + groups.add(map); + } + return groups; + } + + private static List<List<Map<String, String>>> createFilterChildren() { + final List<List<Map<String, String>>> listOfChildGroups = new ArrayList<>(); + + for (final FactoryEntry factoryEntry : FilterRegistry.getInstance().getFactories()) { + final IFilterFactory factory = createFilterFactory(factoryEntry.getFactory()); + final List<? extends IFilter> filters = factory.getFilters(); + + final List<Map<String, String>> childGroups = new ArrayList<>(filters.size()); + + for (final IFilter filter : filters) { + final HashMap<String, String> hashMap = new HashMap<>(1); + hashMap.put(KEY_FILTER_NAME, filter.getName()); + hashMap.put("CHILD_NAME", filter.getName()); + childGroups.add(hashMap); + } + listOfChildGroups.add(childGroups); + } + return listOfChildGroups; + } + + private static IFilterFactory createFilterFactory(final Class<? extends IFilterFactory> class1) { + try { + return class1.newInstance(); + } catch (final InstantiationException e) { + Log.e("createFilterFactory", e); + } catch (final IllegalAccessException e) { + Log.e("createFilterFactory", e); + } + return null; + } + + /** + * After calling this method, the calling activity must implement onActivityResult, and check the + * {@link #EXTRA_FILTER_RESULT}. + */ + public static void selectFilter(@NonNull final Activity context) { + context.startActivityForResult(new Intent(context, FilterActivity_.class), REQUEST_SELECT_FILTER); + } + + @OptionsItem(R.id.menu_reset_filter) + void resetFilter() { + setFilterResult(-1, -1); + } + + private void setFilterResult(final int groupPosition, final int childPosition) { + final Intent resultIntent = new Intent(); + resultIntent.putExtra(EXTRA_FILTER_RESULT, new int[] { groupPosition, childPosition }); + setResult(Activity.RESULT_OK, resultIntent); + finish(); + } +} diff --git a/main/src/cgeo/geocaching/filter/FilterRegistry.java b/main/src/cgeo/geocaching/filter/FilterRegistry.java new file mode 100644 index 0000000..d6d9db9 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/FilterRegistry.java @@ -0,0 +1,86 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.R; +import cgeo.geocaching.filter.SizeFilter.Factory; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; + +import android.content.res.Resources; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * singleton registry of all available filter components + * + */ +public class FilterRegistry { + private final List<FactoryEntry> registry = new ArrayList<>(); + private static Resources res; + + static class FactoryEntry { + private final String name; + private final @NonNull Class<? extends IFilterFactory> filterFactory; + + public FactoryEntry(final String name, final @NonNull Class<? extends IFilterFactory> filterFactory) { + this.name = name; + this.filterFactory = filterFactory; + } + + @Override + public String toString() { + return name; + } + + public String getName() { + return name; + } + + public Class<? extends IFilterFactory> getFactory() { + return filterFactory; + } + } + + private static class SingletonHolder { + private static final FilterRegistry INSTANCE = new FilterRegistry(); + } + + public static FilterRegistry getInstance() { + return SingletonHolder.INSTANCE; + } + + private FilterRegistry() { + res = CgeoApplication.getInstance().getResources(); + register(R.string.caches_filter_type, TypeFilter.Factory.class); + register(R.string.caches_filter_size, SizeFilter.Factory.class); + register(R.string.cache_terrain, TerrainFilter.Factory.class); + register(R.string.cache_difficulty, DifficultyFilter.Factory.class); + register(R.string.cache_attributes, AttributeFilter.Factory.class); + register(R.string.cache_status, StateFilterFactory.class); + register(R.string.caches_filter_origin, OriginFilter.Factory.class); + register(R.string.caches_filter_distance, DistanceFilter.Factory.class); + register(R.string.caches_filter_popularity, PopularityFilter.Factory.class); + register(R.string.caches_filter_popularity_ratio, PopularityRatioFilter.Factory.class); + register(R.string.caches_filter_personal_data, PersonalDataFilterFactory.class); + } + + private void register(final int resourceId, final @NonNull Class<? extends IFilterFactory> factoryClass) { + registry.add(new FactoryEntry(res.getString(resourceId), factoryClass)); + } + + public String getFactoryName(final Class<Factory> factoryClass) { + for (final FactoryEntry entry : registry) { + if (entry.filterFactory == factoryClass) { + return entry.name; + } + } + return StringUtils.EMPTY; + } + + public List<FactoryEntry> getFactories() { + return Collections.unmodifiableList(registry); + } +} diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java deleted file mode 100644 index 9f1d563..0000000 --- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java +++ /dev/null @@ -1,130 +0,0 @@ -package cgeo.geocaching.filter; - -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.R; -import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.settings.Settings; -import cgeo.geocaching.utils.Log; - -import rx.functions.Action1; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.res.Resources; -import android.widget.ArrayAdapter; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -public final class FilterUserInterface { - - private static class FactoryEntry { - private final String name; - private final Class<? extends IFilterFactory> filterFactory; - - public FactoryEntry(final String name, final Class<? extends IFilterFactory> filterFactory) { - this.name = name; - this.filterFactory = filterFactory; - } - - @Override - public String toString() { - return name; - } - } - - private final Activity activity; - private final ArrayList<FactoryEntry> registry; - private final Resources res; - - public FilterUserInterface(final Activity activity) { - this.activity = activity; - this.res = CgeoApplication.getInstance().getResources(); - - registry = new ArrayList<>(); - if (Settings.getCacheType() == CacheType.ALL) { - register(R.string.caches_filter_type, TypeFilter.Factory.class); - } - register(R.string.caches_filter_size, SizeFilter.Factory.class); - register(R.string.cache_terrain, TerrainFilter.Factory.class); - register(R.string.cache_difficulty, DifficultyFilter.Factory.class); - register(R.string.cache_attributes, AttributeFilter.Factory.class); - register(R.string.cache_status, StateFilter.Factory.class); - register(R.string.caches_filter_track, TrackablesFilter.class); - register(R.string.caches_filter_modified, ModifiedFilter.class); - register(R.string.caches_filter_origin, OriginFilter.Factory.class); - register(R.string.caches_filter_distance, DistanceFilter.Factory.class); - register(R.string.caches_filter_personal_note, PersonalNoteFilter.class); - register(R.string.caches_filter_popularity, PopularityFilter.Factory.class); - register(R.string.caches_filter_popularity_ratio, PopularityRatioFilter.Factory.class); - - // sort by localized names - Collections.sort(registry, new Comparator<FactoryEntry>() { - - @Override - public int compare(final FactoryEntry lhs, final FactoryEntry rhs) { - return lhs.name.compareToIgnoreCase(rhs.name); - } - }); - - // reset shall be last - register(R.string.caches_filter_clear, null); - } - - private void register(final int resourceId, final Class<? extends IFilterFactory> factoryClass) { - registry.add(new FactoryEntry(res.getString(resourceId), factoryClass)); - } - - public void selectFilter(final Action1<IFilter> runAfterwards) { - final AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setTitle(R.string.caches_filter_title); - - final ArrayAdapter<FactoryEntry> adapter = new ArrayAdapter<>(activity, android.R.layout.select_dialog_item, registry); - - builder.setAdapter(adapter, new DialogInterface.OnClickListener() { - @Override - public void onClick(final DialogInterface dialog, final int itemIndex) { - FactoryEntry entry = adapter.getItem(itemIndex); - // reset? - if (entry.filterFactory == null) { - runAfterwards.call(null); - } - else { - try { - IFilterFactory factoryInstance = entry.filterFactory.newInstance(); - selectFromFactory(factoryInstance, entry.name, runAfterwards); - } catch (Exception e) { - Log.e("selectFilter", e); - } - } - } - }); - - builder.create().show(); - } - - private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final Action1<IFilter> runAfterwards) { - final List<IFilter> filters = Collections.unmodifiableList(factory.getFilters()); - if (filters.size() == 1) { - runAfterwards.call(filters.get(0)); - return; - } - - final AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setTitle(menuTitle); - - final ArrayAdapter<IFilter> adapter = new ArrayAdapter<>(activity, android.R.layout.select_dialog_item, filters); - builder.setAdapter(adapter, new DialogInterface.OnClickListener() { - @Override - public void onClick(final DialogInterface dialog, final int item) { - runAfterwards.call(filters.get(item)); - } - }); - - builder.create().show(); - } - -} diff --git a/main/src/cgeo/geocaching/filter/IFilter.java b/main/src/cgeo/geocaching/filter/IFilter.java index 4fafe6f..f590f79 100644 --- a/main/src/cgeo/geocaching/filter/IFilter.java +++ b/main/src/cgeo/geocaching/filter/IFilter.java @@ -2,17 +2,21 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; +import org.eclipse.jdt.annotation.NonNull; + import java.util.List; public interface IFilter { + @NonNull String getName(); /** - * @param cache - * @return true if the filter accepts the cache, false otherwise + * @return {@code true} if the filter accepts the cache, false otherwise */ - boolean accepts(final Geocache cache); + boolean accepts(@NonNull final Geocache cache); + + void filter(@NonNull final List<Geocache> list); - void filter(final List<Geocache> list); + int getImageId(); }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/filter/IFilterFactory.java b/main/src/cgeo/geocaching/filter/IFilterFactory.java index afc99af..82e69da 100644 --- a/main/src/cgeo/geocaching/filter/IFilterFactory.java +++ b/main/src/cgeo/geocaching/filter/IFilterFactory.java @@ -1,7 +1,10 @@ package cgeo.geocaching.filter; +import org.eclipse.jdt.annotation.NonNull; + import java.util.List; interface IFilterFactory { + @NonNull List<? extends IFilter> getFilters(); } diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java index 2ac088a..9b5c856 100644 --- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java +++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java @@ -1,25 +1,27 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import java.util.Collections; import java.util.List; class ModifiedFilter extends AbstractFilter implements IFilterFactory { public ModifiedFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_modified)); + super(R.string.caches_filter_modified); } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { // modified on GC return cache.hasUserModifiedCoords() || cache.hasFinalDefined(); } @Override + @NonNull public List<ModifiedFilter> getFilters() { return Collections.singletonList(this); } diff --git a/main/src/cgeo/geocaching/filter/OfflineLogFilter.java b/main/src/cgeo/geocaching/filter/OfflineLogFilter.java new file mode 100644 index 0000000..0ed9618 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/OfflineLogFilter.java @@ -0,0 +1,19 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; + +import org.eclipse.jdt.annotation.NonNull; + +public class OfflineLogFilter extends AbstractFilter { + + protected OfflineLogFilter() { + super(R.string.caches_filter_offline_log); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isLogOffline(); + } + +} diff --git a/main/src/cgeo/geocaching/filter/OriginFilter.java b/main/src/cgeo/geocaching/filter/OriginFilter.java index 99d1c05..d51b02c 100644 --- a/main/src/cgeo/geocaching/filter/OriginFilter.java +++ b/main/src/cgeo/geocaching/filter/OriginFilter.java @@ -4,6 +4,8 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; +import org.eclipse.jdt.annotation.NonNull; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -13,22 +15,23 @@ public class OriginFilter extends AbstractFilter { private final IConnector connector; - public OriginFilter(final IConnector connector) { + public OriginFilter(@NonNull final IConnector connector) { super(connector.getName()); this.connector = connector; } @Override - public final boolean accepts(final Geocache cache) { + public final boolean accepts(@NonNull final Geocache cache) { return ConnectorFactory.getConnector(cache) == connector; } public static final class Factory implements IFilterFactory { @Override + @NonNull public List<OriginFilter> getFilters() { final ArrayList<OriginFilter> filters = new ArrayList<>(); - for (IConnector connector : ConnectorFactory.getConnectors()) { + for (final IConnector connector : ConnectorFactory.getConnectors()) { filters.add(new OriginFilter(connector)); } diff --git a/main/src/cgeo/geocaching/filter/OwnRatingFilter.java b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java new file mode 100644 index 0000000..1b86bab --- /dev/null +++ b/main/src/cgeo/geocaching/filter/OwnRatingFilter.java @@ -0,0 +1,34 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; +import cgeo.geocaching.gcvote.GCVote; + +import org.eclipse.jdt.annotation.NonNull; + +import java.util.Collections; +import java.util.List; + +/** + * Filter {@link Geocache}s if they have a locally stored <b>own</b> {@link GCVote} rating. This filter will not do any + * network request to find potentially missing local votes. + * + */ +public class OwnRatingFilter extends AbstractFilter implements IFilterFactory { + + protected OwnRatingFilter() { + super(R.string.caches_filter_own_rating); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.getMyVote() > 0; + } + + @Override + @NonNull + public List<OwnRatingFilter> getFilters() { + return Collections.singletonList(this); + } + +} diff --git a/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java new file mode 100644 index 0000000..e9780da --- /dev/null +++ b/main/src/cgeo/geocaching/filter/PersonalDataFilterFactory.java @@ -0,0 +1,16 @@ +package cgeo.geocaching.filter; + +import org.eclipse.jdt.annotation.NonNull; + +import java.util.Arrays; +import java.util.List; + +public class PersonalDataFilterFactory implements IFilterFactory { + + @Override + @NonNull + public List<? extends IFilter> getFilters() { + return Arrays.asList(new OwnRatingFilter(), new PersonalNoteFilter(), new ModifiedFilter(), new OfflineLogFilter()); + } + +} diff --git a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java index 15d262f..11c623e 100644 --- a/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java +++ b/main/src/cgeo/geocaching/filter/PersonalNoteFilter.java @@ -1,26 +1,30 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import java.util.Collections; import java.util.List; +/** + * Filter that accepts {@link Geocache}s with a non empty personal note stored locally. + */ public class PersonalNoteFilter extends AbstractFilter implements IFilterFactory { protected PersonalNoteFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_personal_note)); + super(R.string.caches_filter_personal_note); } @Override - public boolean accepts(Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { return StringUtils.isNotBlank(cache.getPersonalNote()); } @Override + @NonNull public List<PersonalNoteFilter> getFilters() { return Collections.singletonList(this); } diff --git a/main/src/cgeo/geocaching/filter/PopularityFilter.java b/main/src/cgeo/geocaching/filter/PopularityFilter.java index a0244b9..eabc533 100644 --- a/main/src/cgeo/geocaching/filter/PopularityFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityFilter.java @@ -4,6 +4,8 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import java.util.ArrayList; import java.util.List; @@ -11,14 +13,14 @@ class PopularityFilter extends AbstractFilter { private final int minFavorites; private final int maxFavorites; - public PopularityFilter(String name, final int minFavorites, final int maxFavorites) { + public PopularityFilter(@NonNull final String name, final int minFavorites, final int maxFavorites) { super(name); this.minFavorites = minFavorites; this.maxFavorites = maxFavorites; } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { return (cache.getFavoritePoints() > minFavorites) && (cache.getFavoritePoints() <= maxFavorites); } @@ -27,10 +29,10 @@ class PopularityFilter extends AbstractFilter { private static final int[] FAVORITES = { 10, 20, 50, 100, 200, 500 }; @Override + @NonNull public List<IFilter> getFilters() { final List<IFilter> filters = new ArrayList<>(FAVORITES.length); - for (int i = 0; i < FAVORITES.length; i++) { - final int minRange = FAVORITES[i]; + for (final int minRange : FAVORITES) { final int maxRange = Integer.MAX_VALUE; final String range = "> " + minRange; final String name = CgeoApplication.getInstance().getResources().getQuantityString(R.plurals.favorite_points, minRange, range); diff --git a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java index a04f219..0548345 100644 --- a/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java +++ b/main/src/cgeo/geocaching/filter/PopularityRatioFilter.java @@ -6,6 +6,8 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.enumerations.LogType; +import org.eclipse.jdt.annotation.NonNull; + import java.util.ArrayList; import java.util.List; @@ -16,14 +18,14 @@ class PopularityRatioFilter extends AbstractFilter { private final int minRatio; private final int maxRatio; - public PopularityRatioFilter(String name, final int minRatio, final int maxRatio) { + public PopularityRatioFilter(@NonNull final String name, final int minRatio, final int maxRatio) { super(name); this.minRatio = minRatio; this.maxRatio = maxRatio; } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { final int finds = getFindsCount(cache); if (finds == 0) { // Prevent division by zero @@ -35,11 +37,11 @@ class PopularityRatioFilter extends AbstractFilter { return ratio > minRatio && ratio <= maxRatio; } - private static int getFindsCount(Geocache cache) { + private static int getFindsCount(final Geocache cache) { if (cache.getLogCounts().isEmpty()) { cache.setLogCounts(DataStore.loadLogCounts(cache.getGeocode())); } - Integer logged = cache.getLogCounts().get(LogType.FOUND_IT); + final Integer logged = cache.getLogCounts().get(LogType.FOUND_IT); if (logged != null) { return logged; } @@ -51,12 +53,12 @@ class PopularityRatioFilter extends AbstractFilter { private static final int[] RATIOS = { 10, 20, 30, 40, 50, 75 }; @Override + @NonNull public List<IFilter> getFilters() { final List<IFilter> filters = new ArrayList<>(RATIOS.length); - for (int i = 0; i < RATIOS.length; i++) { - final int minRange = RATIOS[i]; + for (final int minRange : RATIOS) { final int maxRange = Integer.MAX_VALUE; - final String name = "> " + minRange + " " + CgeoApplication.getInstance().getResources().getString(R.string.percent_favorite_points); + final String name = CgeoApplication.getInstance().getResources().getString(R.string.more_than_percent_favorite_points, minRange); filters.add(new PopularityRatioFilter(name, minRange, maxRange)); } return filters; diff --git a/main/src/cgeo/geocaching/filter/RatingFilter.java b/main/src/cgeo/geocaching/filter/RatingFilter.java new file mode 100644 index 0000000..16ce16c --- /dev/null +++ b/main/src/cgeo/geocaching/filter/RatingFilter.java @@ -0,0 +1,25 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; +import cgeo.geocaching.gcvote.GCVote; + +import org.eclipse.jdt.annotation.NonNull; + +/** + * Filter {@link Geocache}s if they have a locally stored {@link GCVote} rating. This filter will not do any network + * request to find potentially missing local votes. + * + */ +public class RatingFilter extends AbstractFilter { + + protected RatingFilter() { + super(R.string.caches_filter_rating); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.getRating() > 0; + } + +} diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java index f02874c..a19d95b 100644 --- a/main/src/cgeo/geocaching/filter/SizeFilter.java +++ b/main/src/cgeo/geocaching/filter/SizeFilter.java @@ -3,23 +3,26 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheSize; +import org.eclipse.jdt.annotation.NonNull; + import java.util.LinkedList; import java.util.List; class SizeFilter extends AbstractFilter { private final CacheSize cacheSize; - public SizeFilter(final CacheSize cacheSize) { + public SizeFilter(@NonNull final CacheSize cacheSize) { super(cacheSize.id); this.cacheSize = cacheSize; } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { return cacheSize == cache.getSize(); } @Override + @NonNull public String getName() { return cacheSize.getL10n(); } @@ -27,16 +30,17 @@ class SizeFilter extends AbstractFilter { public static class Factory implements IFilterFactory { @Override + @NonNull public List<IFilter> getFilters() { final CacheSize[] cacheSizes = CacheSize.values(); final List<IFilter> filters = new LinkedList<>(); - for (CacheSize cacheSize : cacheSizes) { + for (final CacheSize cacheSize : cacheSizes) { if (cacheSize != CacheSize.UNKNOWN) { filters.add(new SizeFilter(cacheSize)); } } return filters; } - } + } diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java deleted file mode 100644 index ebe133c..0000000 --- a/main/src/cgeo/geocaching/filter/StateFilter.java +++ /dev/null @@ -1,153 +0,0 @@ -package cgeo.geocaching.filter; - -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.Geocache; -import cgeo.geocaching.R; - -import android.content.res.Resources; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -abstract class StateFilter extends AbstractFilter { - - static final Resources res = CgeoApplication.getInstance().getResources(); - - protected StateFilter(final String name) { - super(name); - } - - static class StateFoundFilter extends StateFilter { - - public StateFoundFilter() { - super(res.getString(R.string.cache_status_found)); - } - - @Override - public boolean accepts(final Geocache cache) { - return cache.isFound(); - } - - } - - static class StateNotFoundFilter extends StateFilter { - - public StateNotFoundFilter() { - super(res.getString(R.string.cache_not_status_found)); - } - - @Override - public boolean accepts(final Geocache cache) { - return !cache.isFound(); - } - - } - - static class StateArchivedFilter extends StateFilter { - public StateArchivedFilter() { - super(res.getString(R.string.cache_status_archived)); - } - - @Override - public boolean accepts(final Geocache cache) { - return cache.isArchived(); - } - } - - static class StateDisabledFilter extends StateFilter { - public StateDisabledFilter() { - super(res.getString(R.string.cache_status_disabled)); - } - - @Override - public boolean accepts(final Geocache cache) { - return cache.isDisabled(); - } - } - - static class StatePremiumFilter extends StateFilter { - public StatePremiumFilter() { - super(res.getString(R.string.cache_status_premium)); - } - - @Override - public boolean accepts(final Geocache cache) { - return cache.isPremiumMembersOnly(); - } - } - - static class StateNonPremiumFilter extends StateFilter { - public StateNonPremiumFilter() { - super(res.getString(R.string.cache_status_not_premium)); - } - - @Override - public boolean accepts(final Geocache cache) { - return !cache.isPremiumMembersOnly(); - } - } - - private static class StateOfflineLogFilter extends StateFilter { - public StateOfflineLogFilter() { - super(res.getString(R.string.cache_status_offline_log)); - } - - @Override - public boolean accepts(final Geocache cache) { - return cache.isLogOffline(); - } - } - - static class StateStoredFilter extends StateFilter { - public StateStoredFilter() { - super(res.getString(R.string.cache_status_stored)); - } - - @Override - public boolean accepts(final Geocache cache) { - return cache.isOffline(); - } - } - - static class StateNotStoredFilter extends StateFilter { - public StateNotStoredFilter() { - super(res.getString(R.string.cache_status_not_stored)); - } - - @Override - public boolean accepts(final Geocache cache) { - return !cache.isOffline(); - } - } - - public static class Factory implements IFilterFactory { - - @Override - public List<StateFilter> getFilters() { - final List<StateFilter> filters = new ArrayList<>(6); - filters.add(new StateFoundFilter()); - filters.add(new StateNotFoundFilter()); - filters.add(new StateArchivedFilter()); - filters.add(new StateDisabledFilter()); - filters.add(new StatePremiumFilter()); - filters.add(new StateNonPremiumFilter()); - filters.add(new StateOfflineLogFilter()); - filters.add(new StateStoredFilter()); - filters.add(new StateNotStoredFilter()); - - Collections.sort(filters, new Comparator<StateFilter>() { - - @Override - public int compare(final StateFilter filter1, final StateFilter filter2) { - return String.CASE_INSENSITIVE_ORDER.compare(filter1.getName(), filter2.getName()); - } - }); - - return filters; - } - - } - -} diff --git a/main/src/cgeo/geocaching/filter/StateFilterFactory.java b/main/src/cgeo/geocaching/filter/StateFilterFactory.java new file mode 100644 index 0000000..42de764 --- /dev/null +++ b/main/src/cgeo/geocaching/filter/StateFilterFactory.java @@ -0,0 +1,145 @@ +package cgeo.geocaching.filter; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; + +import org.eclipse.jdt.annotation.NonNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +class StateFilterFactory implements IFilterFactory { + + @Override + @NonNull + public List<? extends IFilter> getFilters() { + final List<AbstractFilter> filters = new ArrayList<>(6); + filters.add(new StateFoundFilter()); + filters.add(new StateNotFoundFilter()); + filters.add(new StateArchivedFilter()); + filters.add(new StateDisabledFilter()); + filters.add(new StatePremiumFilter()); + filters.add(new StateNonPremiumFilter()); + filters.add(new StateOfflineLogFilter()); + filters.add(new StateStoredFilter()); + filters.add(new StateNotStoredFilter()); + filters.add(new RatingFilter()); + filters.add(new TrackablesFilter()); + + Collections.sort(filters, new Comparator<AbstractFilter>() { + + @Override + public int compare(final AbstractFilter filter1, final AbstractFilter filter2) { + return String.CASE_INSENSITIVE_ORDER.compare(filter1.getName(), filter2.getName()); + } + }); + + return filters; + } + + static class StateFoundFilter extends AbstractFilter { + + public StateFoundFilter() { + super(R.string.cache_status_found); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isFound(); + } + + } + + static class StateNotFoundFilter extends AbstractFilter { + + public StateNotFoundFilter() { + super(R.string.cache_not_status_found); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return !cache.isFound(); + } + + } + + static class StateArchivedFilter extends AbstractFilter { + public StateArchivedFilter() { + super(R.string.cache_status_archived); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isArchived(); + } + } + + static class StateDisabledFilter extends AbstractFilter { + public StateDisabledFilter() { + super(R.string.cache_status_disabled); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isDisabled(); + } + } + + static class StatePremiumFilter extends AbstractFilter { + public StatePremiumFilter() { + super(R.string.cache_status_premium); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isPremiumMembersOnly(); + } + } + + static class StateNonPremiumFilter extends AbstractFilter { + public StateNonPremiumFilter() { + super(R.string.cache_status_not_premium); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return !cache.isPremiumMembersOnly(); + } + } + + private static class StateOfflineLogFilter extends AbstractFilter { + public StateOfflineLogFilter() { + super(R.string.cache_status_offline_log); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isLogOffline(); + } + } + + static class StateStoredFilter extends AbstractFilter { + public StateStoredFilter() { + super(R.string.cache_status_stored); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return cache.isOffline(); + } + } + + static class StateNotStoredFilter extends AbstractFilter { + public StateNotStoredFilter() { + super(R.string.cache_status_not_stored); + } + + @Override + public boolean accepts(@NonNull final Geocache cache) { + return !cache.isOffline(); + } + } + +} diff --git a/main/src/cgeo/geocaching/filter/TerrainFilter.java b/main/src/cgeo/geocaching/filter/TerrainFilter.java index 7da6a19..977e4a5 100644 --- a/main/src/cgeo/geocaching/filter/TerrainFilter.java +++ b/main/src/cgeo/geocaching/filter/TerrainFilter.java @@ -3,6 +3,8 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import org.eclipse.jdt.annotation.NonNull; + import java.util.ArrayList; import java.util.List; @@ -13,7 +15,7 @@ class TerrainFilter extends AbstractRangeFilter { } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { final float terrain = cache.getTerrain(); return rangeMin <= terrain && terrain < rangeMax; } @@ -23,6 +25,7 @@ class TerrainFilter extends AbstractRangeFilter { private static final int TERRAIN_MAX = 7; @Override + @NonNull public List<IFilter> getFilters() { final ArrayList<IFilter> filters = new ArrayList<>(TERRAIN_MAX); for (int terrain = TERRAIN_MIN; terrain <= TERRAIN_MAX; terrain++) { diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java index d836a0f..debe11f 100644 --- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java +++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java @@ -1,25 +1,18 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; -import java.util.Collections; -import java.util.List; +import org.eclipse.jdt.annotation.NonNull; -class TrackablesFilter extends AbstractFilter implements IFilterFactory { +class TrackablesFilter extends AbstractFilter { public TrackablesFilter() { - super(CgeoApplication.getInstance().getString(R.string.caches_filter_track)); + super(R.string.caches_filter_track); } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { return cache.hasTrackables(); } - @Override - public List<TrackablesFilter> getFilters() { - return Collections.singletonList(this); - } - } diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java index d363d39..b8c879f 100644 --- a/main/src/cgeo/geocaching/filter/TypeFilter.java +++ b/main/src/cgeo/geocaching/filter/TypeFilter.java @@ -3,23 +3,26 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheType; +import org.eclipse.jdt.annotation.NonNull; + import java.util.LinkedList; import java.util.List; class TypeFilter extends AbstractFilter { private final CacheType cacheType; - public TypeFilter(final CacheType cacheType) { + public TypeFilter(@NonNull final CacheType cacheType) { super(cacheType.id); this.cacheType = cacheType; } @Override - public boolean accepts(final Geocache cache) { + public boolean accepts(@NonNull final Geocache cache) { return cacheType == cache.getType(); } @Override + @NonNull public String getName() { return cacheType.getL10n(); } @@ -27,10 +30,11 @@ class TypeFilter extends AbstractFilter { public static class Factory implements IFilterFactory { @Override + @NonNull public List<IFilter> getFilters() { final CacheType[] types = CacheType.values(); final List<IFilter> filters = new LinkedList<>(); - for (CacheType cacheType : types) { + for (final CacheType cacheType : types) { if (cacheType != CacheType.ALL) { filters.add(new TypeFilter(cacheType)); } @@ -39,4 +43,9 @@ class TypeFilter extends AbstractFilter { } } + + @Override + public int getImageId() { + return cacheType.markerId; + } } diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index 8de3edc..2985e89 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -8,13 +8,18 @@ import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.LeastRecentlyUsedMap; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.MatcherWrapper; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserFactory; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -22,17 +27,9 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.regex.Pattern; public final class GCVote { public static final float NO_RATING = 0; - private static final Pattern PATTERN_LOG_IN = Pattern.compile("loggedIn='([^']+)'", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_GUID = Pattern.compile("cacheId='([^']+)'", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_WAYPOINT = Pattern.compile("waypoint='([^']+)'", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_RATING = Pattern.compile("voteAvg='([0-9.]+)'", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_VOTES = Pattern.compile("voteCnt='([0-9]+)'", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_VOTE = Pattern.compile("voteUser='([0-9.]+)'", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_VOTE_ELEMENT = Pattern.compile("<vote ([^>]+)>", Pattern.CASE_INSENSITIVE); private static final int MAX_CACHED_RATINGS = 1000; private static final LeastRecentlyUsedMap<String, GCVoteRating> RATINGS_CACHE = new LeastRecentlyUsedMap.LruCache<>(MAX_CACHED_RATINGS); @@ -46,10 +43,6 @@ public final class GCVote { /** * Get user rating for a given guid or geocode. For a guid first the ratings cache is checked * before a request to gcvote.com is made. - * - * @param guid - * @param geocode - * @return */ public static GCVoteRating getRating(final String guid, final String geocode) { if (StringUtils.isNotBlank(guid) && RATINGS_CACHE.containsKey(guid)) { @@ -66,161 +59,100 @@ public final class GCVote { /** * Get user ratings from gcvote.com - * - * @param guids - * @param geocodes - * @return */ + @NonNull private static Map<String, GCVoteRating> getRating(final List<String> guids, final List<String> geocodes) { if (guids == null && geocodes == null) { - return null; + return Collections.emptyMap(); } - final Map<String, GCVoteRating> ratings = new HashMap<>(); + final Parameters params = new Parameters("version", "cgeo"); + final ImmutablePair<String, String> login = Settings.getGCvoteLogin(); + if (login != null) { + params.put("userName", login.left, "password", login.right); + } + // use guid or gccode for lookup + final boolean requestByGuids = CollectionUtils.isNotEmpty(guids); + if (requestByGuids) { + params.put("cacheIds", StringUtils.join(guids, ',')); + } else { + params.put("waypoints", StringUtils.join(geocodes, ',')); + } + final InputStream response = Network.getResponseStream(Network.getRequest("http://gcvote.com/getVotes.php", params)); + if (response == null) { + return Collections.emptyMap(); + } try { - final Parameters params = new Parameters(); - if (Settings.isLogin()) { - final ImmutablePair<String, String> login = Settings.getGCvoteLogin(); - if (login != null) { - params.put("userName", login.left, "password", login.right); - } - } - // use guid or gccode for lookup - boolean requestByGuids = true; - if (guids != null && !guids.isEmpty()) { - params.put("cacheIds", StringUtils.join(guids.toArray(), ',')); - } else { - params.put("waypoints", StringUtils.join(geocodes.toArray(), ',')); - requestByGuids = false; - } - params.put("version", "cgeo"); - final String page = Network.getResponseData(Network.getRequest("http://gcvote.com/getVotes.php", params)); - if (page == null) { - return null; - } - - final MatcherWrapper matcherVoteElement = new MatcherWrapper(PATTERN_VOTE_ELEMENT, page); - while (matcherVoteElement.find()) { - String voteData = matcherVoteElement.group(1); - if (voteData == null) { - continue; - } - - String id = null; - String guid = null; - final MatcherWrapper matcherGuid = new MatcherWrapper(PATTERN_GUID, voteData); - if (matcherGuid.find()) { - if (matcherGuid.groupCount() > 0) { - guid = matcherGuid.group(1); - if (requestByGuids) { - id = guid; - } - } - } - if (!requestByGuids) { - final MatcherWrapper matcherWp = new MatcherWrapper(PATTERN_WAYPOINT, voteData); - if (matcherWp.find()) { - if (matcherWp.groupCount() > 0) { - id = matcherWp.group(1); - } - } - } - if (id == null) { - continue; - } - - boolean loggedIn = false; - final MatcherWrapper matcherLoggedIn = new MatcherWrapper(PATTERN_LOG_IN, page); - if (matcherLoggedIn.find()) { - if (matcherLoggedIn.groupCount() > 0) { - if (matcherLoggedIn.group(1).equalsIgnoreCase("true")) { - loggedIn = true; - } - } - } - - float rating = NO_RATING; - try { - final MatcherWrapper matcherRating = new MatcherWrapper(PATTERN_RATING, voteData); - if (matcherRating.find()) { - rating = Float.parseFloat(matcherRating.group(1)); - } - } catch (NumberFormatException e) { - Log.w("GCVote.getRating: Failed to parse rating"); - } - if (!isValidRating(rating)) { - continue; - } - - int votes = -1; - try { - final MatcherWrapper matcherVotes = new MatcherWrapper(PATTERN_VOTES, voteData); - if (matcherVotes.find()) { - votes = Integer.parseInt(matcherVotes.group(1)); - } - } catch (NumberFormatException e) { - Log.w("GCVote.getRating: Failed to parse vote count"); - } - if (votes < 0) { - continue; - } + return getRatingsFromXMLResponse(response, requestByGuids); + } finally { + IOUtils.closeQuietly(response); + } + } - float myVote = NO_RATING; - if (loggedIn) { - try { - final MatcherWrapper matcherVote = new MatcherWrapper(PATTERN_VOTE, voteData); - if (matcherVote.find()) { - myVote = Float.parseFloat(matcherVote.group(1)); - } - } catch (NumberFormatException e) { - Log.w("GCVote.getRating: Failed to parse user's vote"); + static Map<String, GCVoteRating> getRatingsFromXMLResponse(@NonNull final InputStream response, final boolean requestByGuids) { + try { + final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + final XmlPullParser xpp = factory.newPullParser(); + xpp.setInput(response, Charsets.UTF_8.name()); + boolean loggedIn = false; + final Map<String, GCVoteRating> ratings = new HashMap<>(); + int eventType = xpp.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + final String tagName = xpp.getName(); + if (StringUtils.equals(tagName, "vote")) { + final String id = xpp.getAttributeValue(null, requestByGuids ? "cacheId" : "waypoint"); + final float myVote = loggedIn ? Float.parseFloat(xpp.getAttributeValue(null, "voteUser")) : 0; + final GCVoteRating voteRating = new GCVoteRating(Float.parseFloat(xpp.getAttributeValue(null, "voteAvg")), + Integer.parseInt(xpp.getAttributeValue(null, "voteCnt")), + myVote); + ratings.put(id, voteRating); + } else if (StringUtils.equals(tagName, "votes")) { + loggedIn = StringUtils.equals(xpp.getAttributeValue(null, "loggedIn"), "true"); } } - - if (StringUtils.isNotBlank(id)) { - GCVoteRating gcvoteRating = new GCVoteRating(rating, votes, myVote); - ratings.put(id, gcvoteRating); - RATINGS_CACHE.put(guid, gcvoteRating); - } + eventType = xpp.next(); } - } catch (RuntimeException e) { - Log.e("GCVote.getRating", e); - } + RATINGS_CACHE.putAll(ratings); + return ratings; + } catch (final Exception e) { + Log.e("Cannot parse GC vote result", e); + return Collections.emptyMap(); - return ratings; + } } /** * Transmit user vote to gcvote.com * - * @param cache - * @param vote + * @param cache the geocache (supported by GCVote) + * @param rating the rating * @return {@code true} if the rating was submitted successfully */ - public static boolean setRating(final Geocache cache, final float vote) { + public static boolean setRating(final Geocache cache, final float rating) { if (!isVotingPossible(cache)) { - return false; + throw new IllegalArgumentException("voting is not possible for " + cache); } - if (!isValidRating(vote)) { - return false; + if (!isValidRating(rating)) { + throw new IllegalArgumentException("invalid rating " + rating); } final ImmutablePair<String, String> login = Settings.getGCvoteLogin(); - if (login == null) { - return false; - } - final Parameters params = new Parameters( "userName", login.left, "password", login.right, "cacheId", cache.getGuid(), - "voteUser", String.format("%.1f", vote).replace(',', '.'), + "waypoint", cache.getGeocode(), + "voteUser", String.format(Locale.US, "%.1f", rating), "version", "cgeo"); - final String result = Network.getResponseData(Network.getRequest("http://gcvote.com/setVote.php", params)); - - return result != null && result.trim().equalsIgnoreCase("ok"); + final String result = StringUtils.trim(Network.getResponseData(Network.getRequest("http://gcvote.com/setVote.php", params))); + if (!StringUtils.equalsIgnoreCase(result, "ok")) { + Log.e("GCVote.setRating: could not post rating, answer was " + result); + return false; + } + return true; } public static void loadRatings(final @NonNull ArrayList<Geocache> caches) { @@ -236,34 +168,29 @@ public final class GCVote { try { final Map<String, GCVoteRating> ratings = GCVote.getRating(null, geocodes); - if (MapUtils.isNotEmpty(ratings)) { - // save found cache coordinates - for (Geocache cache : caches) { - if (ratings.containsKey(cache.getGeocode())) { - GCVoteRating rating = ratings.get(cache.getGeocode()); + // save found cache coordinates + for (final Geocache cache : caches) { + if (ratings.containsKey(cache.getGeocode())) { + final GCVoteRating rating = ratings.get(cache.getGeocode()); - cache.setRating(rating.getRating()); - cache.setVotes(rating.getVotes()); - cache.setMyVote(rating.getMyVote()); - } + cache.setRating(rating.getRating()); + cache.setVotes(rating.getVotes()); + cache.setMyVote(rating.getMyVote()); } } - } catch (Exception e) { + } catch (final Exception e) { Log.e("GCvote.loadRatings", e); } } /** * Get geocodes of all the caches, which can be used with GCVote. Non-GC caches will be filtered out. - * - * @param caches - * @return */ private static @NonNull ArrayList<String> getVotableGeocodes(final @NonNull Collection<Geocache> caches) { final ArrayList<String> geocodes = new ArrayList<>(caches.size()); for (final Geocache cache : caches) { - String geocode = cache.getGeocode(); + final String geocode = cache.getGeocode(); if (StringUtils.isNotBlank(geocode) && cache.supportsGCVote()) { geocodes.add(geocode); } @@ -275,11 +202,7 @@ public final class GCVote { return rating >= MIN_RATING && rating <= MAX_RATING; } - public static String getRatingText(final float rating) { - return String.format(Locale.getDefault(), "%.1f", rating); - } - - public static boolean isVotingPossible(final Geocache cache) { + public static boolean isVotingPossible(@NonNull final Geocache cache) { return Settings.isGCvoteLogin() && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote(); } @@ -308,7 +231,7 @@ public final class GCVote { } } - private static String getString(int resId) { + private static String getString(final int resId) { return CgeoApplication.getInstance().getString(resId); } diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java new file mode 100644 index 0000000..0738274 --- /dev/null +++ b/main/src/cgeo/geocaching/gcvote/GCVoteDialog.java @@ -0,0 +1,112 @@ +package cgeo.geocaching.gcvote; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.DataStore; +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; +import cgeo.geocaching.gcvote.GCVoteRatingBarUtil.OnRatingChangeListener; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import org.eclipse.jdt.annotation.Nullable; + +import rx.functions.Action1; +import rx.functions.Func0; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.view.ContextThemeWrapper; +import android.view.View; +import android.widget.Button; +import android.widget.Toast; + +/** + * Small dialog showing only a rating bar to vote on GCVote.com. Confirming the dialog will send the vote over the + * network (in the background). + */ +public class GCVoteDialog { + + public static void show(final Activity context, final Geocache cache, final @Nullable Runnable afterVoteSent) { + final Context themedContext; + + if (Settings.isLightSkin() && VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) { + themedContext = new ContextThemeWrapper(context, R.style.dark); + } else { + themedContext = context; + } + + final View votingLayout = View.inflate(themedContext, R.layout.gcvote_dialog, null); + + final AlertDialog.Builder builder = new AlertDialog.Builder(themedContext); + builder.setView(votingLayout); + builder.setPositiveButton(R.string.cache_menu_vote, new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + vote(cache, GCVoteRatingBarUtil.getRating(votingLayout), afterVoteSent); + } + }); + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int whichButton) { + dialog.dismiss(); + } + }); + final AlertDialog dialog = builder.create(); + + GCVoteRatingBarUtil.initializeRatingBar(cache, votingLayout, new OnRatingChangeListener() { + + @Override + public void onRatingChanged(final float stars) { + final Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE); + // this listener might be fired already while the dialog is not yet shown + if (button != null) { + button.setEnabled(GCVote.isValidRating(stars)); + } + } + }); + dialog.show(); + dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(GCVote.isValidRating(cache.getMyVote())); + } + + private static void vote(final Geocache cache, final float rating, final @Nullable Runnable afterVoteSent) { + RxUtils.andThenOnUi(RxUtils.networkScheduler, new Func0<Boolean>() { + @Override + public Boolean call() { + try { + if (GCVote.isValidRating(rating) && GCVote.isVotingPossible(cache)) { + // send over network + if (GCVote.setRating(cache, rating)) { + // store locally + cache.setMyVote(rating); + DataStore.saveChangedCache(cache); + return true; + } + Log.w("GCVoteDialog.vote: could not send vote"); + } + } catch (final RuntimeException e) { + Log.e("GCVoteDialog.vote: could not send vote", e); + } + + return false; + } + }, new Action1<Boolean>() { + @Override + public void call(final Boolean status) { + final CgeoApplication context = CgeoApplication.getInstance(); + final String text = context.getString(status ? R.string.gcvote_sent : R.string.err_gcvote_send_rating); + Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); + if (afterVoteSent != null) { + afterVoteSent.run(); + } + } + }); + } + +} diff --git a/main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java b/main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java new file mode 100644 index 0000000..2d485bd --- /dev/null +++ b/main/src/cgeo/geocaching/gcvote/GCVoteRatingBarUtil.java @@ -0,0 +1,58 @@ +package cgeo.geocaching.gcvote; + +import butterknife.ButterKnife; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; + +import org.eclipse.jdt.annotation.Nullable; + +import android.view.View; +import android.widget.RatingBar; +import android.widget.RatingBar.OnRatingBarChangeListener; +import android.widget.TextView; + +/** + * TODO: convert to fragment + * + */ +public final class GCVoteRatingBarUtil { + public interface OnRatingChangeListener { + public void onRatingChanged(final float stars); + } + + private GCVoteRatingBarUtil() { + // utility class + } + + public static void initializeRatingBar(final Geocache cache, final View parentView, @Nullable final OnRatingChangeListener changeListener) { + if (GCVote.isVotingPossible(cache)) { + final RatingBar ratingBar = ButterKnife.findById(parentView, R.id.gcvoteRating); + final TextView label = ButterKnife.findById(parentView, R.id.gcvoteLabel); + ratingBar.setVisibility(View.VISIBLE); + label.setVisibility(View.VISIBLE); + ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { + + @Override + public void onRatingChanged(final RatingBar ratingBar, final float stars, final boolean fromUser) { + // 0.5 is not a valid rating, therefore we must limit + final float rating = GCVote.isValidRating(stars) ? stars : 0; + if (rating < stars) { + ratingBar.setRating(rating); + } + label.setText(GCVote.getDescription(rating)); + if (changeListener != null) { + changeListener.onRatingChanged(rating); + } + } + }); + ratingBar.setRating(cache.getMyVote()); + } + } + + public static float getRating(final View parentView) { + final RatingBar ratingBar = ButterKnife.findById(parentView, R.id.gcvoteRating); + return ratingBar.getRating(); + } + +} diff --git a/main/src/cgeo/geocaching/list/AbstractList.java b/main/src/cgeo/geocaching/list/AbstractList.java index 9b57b3a..5836e6c 100644 --- a/main/src/cgeo/geocaching/list/AbstractList.java +++ b/main/src/cgeo/geocaching/list/AbstractList.java @@ -8,7 +8,7 @@ public abstract class AbstractList { public final int id; public final String title; - private static SparseArray<AbstractList> LISTS = new SparseArray<>(); + private final static SparseArray<AbstractList> LISTS = new SparseArray<>(); public AbstractList(final int id, final String title) { this.id = id; @@ -25,7 +25,7 @@ public abstract class AbstractList { public abstract int getNumberOfCaches(); @Nullable - public static AbstractList getListById(int listId) { + public static AbstractList getListById(final int listId) { return LISTS.get(listId); } diff --git a/main/src/cgeo/geocaching/list/ListNameMemento.java b/main/src/cgeo/geocaching/list/ListNameMemento.java new file mode 100644 index 0000000..6d5d481 --- /dev/null +++ b/main/src/cgeo/geocaching/list/ListNameMemento.java @@ -0,0 +1,21 @@ +package cgeo.geocaching.list; + +import org.apache.commons.lang3.StringUtils; + +/** + * Memento to remember list name suggestions from search terms. + */ +public class ListNameMemento { + public static final ListNameMemento EMPTY = new ListNameMemento(); + private String newListName = StringUtils.EMPTY; + + public String rememberTerm(final String term) { + newListName = term; + return term; + } + + public String getTerm() { + return newListName; + } + +} diff --git a/main/src/cgeo/geocaching/list/StoredList.java b/main/src/cgeo/geocaching/list/StoredList.java index 53632a0..0ffd58a 100644 --- a/main/src/cgeo/geocaching/list/StoredList.java +++ b/main/src/cgeo/geocaching/list/StoredList.java @@ -24,12 +24,12 @@ import java.util.Comparator; import java.util.List; public final class StoredList extends AbstractList { - public static final int TEMPORARY_LIST_ID = 0; - public static final StoredList TEMPORARY_LIST = new StoredList(TEMPORARY_LIST_ID, "<temporary>", 0); // Never displayed + private static final int TEMPORARY_LIST_ID = 0; + public static final StoredList TEMPORARY_LIST = new StoredList(TEMPORARY_LIST_ID, "<temporary>", 0); // Never displayed public static final int STANDARD_LIST_ID = 1; private final int count; // this value is only valid as long as the list is not changed by other database operations - public StoredList(int id, String title, int count) { + public StoredList(final int id, final String title, final int count) { super(id, title); this.count = count; } @@ -48,7 +48,7 @@ public final class StoredList extends AbstractList { } @Override - public boolean equals(Object obj) { + public boolean equals(final Object obj) { if (this == obj) { return true; } @@ -69,34 +69,30 @@ public final class StoredList extends AbstractList { res = app.getResources(); } - public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards) { - promptForListSelection(titleId, runAfterwards, false, -1); - } - public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId) { - promptForListSelection(titleId, runAfterwards, onlyConcreteLists, exceptListId, StringUtils.EMPTY); + promptForListSelection(titleId, runAfterwards, onlyConcreteLists, exceptListId, ListNameMemento.EMPTY); } - public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final String newListName) { + public void promptForListSelection(final int titleId, @NonNull final Action1<Integer> runAfterwards, final boolean onlyConcreteLists, final int exceptListId, final @NonNull ListNameMemento listNameMemento) { final List<AbstractList> lists = getMenuLists(onlyConcreteLists, exceptListId); final List<CharSequence> listsTitle = new ArrayList<>(); - for (AbstractList list : lists) { + for (final AbstractList list : lists) { listsTitle.add(list.getTitleAndCount()); } final CharSequence[] items = new CharSequence[listsTitle.size()]; final Activity activity = activityRef.get(); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(res.getString(titleId)); builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialogInterface, int itemId) { + public void onClick(final DialogInterface dialogInterface, final int itemId) { final AbstractList list = lists.get(itemId); if (list == PseudoList.NEW_LIST) { // create new list on the fly - promptForListCreation(runAfterwards, newListName); + promptForListCreation(runAfterwards, listNameMemento.getTerm()); } else { runAfterwards.call(lists.get(itemId).id); @@ -106,15 +102,12 @@ public final class StoredList extends AbstractList { builder.create().show(); } - public static List<AbstractList> getMenuLists(boolean onlyConcreteLists, int exceptListId) { + public static List<AbstractList> getMenuLists(final boolean onlyConcreteLists, final int exceptListId) { final List<AbstractList> lists = new ArrayList<>(); lists.addAll(getSortedLists()); - if (exceptListId > StoredList.TEMPORARY_LIST_ID) { - StoredList exceptList = DataStore.getList(exceptListId); - if (exceptList != null) { - lists.remove(exceptList); - } + if (exceptListId == StoredList.STANDARD_LIST_ID || exceptListId >= DataStore.customListIdOffset) { + lists.remove(DataStore.getList(exceptListId)); } if (!onlyConcreteLists) { @@ -138,7 +131,7 @@ public final class StoredList extends AbstractList { Collections.sort(lists, new Comparator<StoredList>() { @Override - public int compare(StoredList lhs, StoredList rhs) { + public int compare(final StoredList lhs, final StoredList rhs) { // have the standard list at the top if (lhs.id == STANDARD_LIST_ID) { return -1; @@ -153,7 +146,7 @@ public final class StoredList extends AbstractList { return lists; } - public void promptForListCreation(@NonNull final Action1<Integer> runAfterwards, String newListName) { + public void promptForListCreation(@NonNull final Action1<Integer> runAfterwards, final String newListName) { handleListNameInput(newListName, R.string.list_dialog_create_title, R.string.list_dialog_create, new Action1<String>() { // We need to update the list cache by creating a new StoredList object here. @@ -177,7 +170,7 @@ public final class StoredList extends AbstractList { }); } - private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final Action1<String> runnable) { + private void handleListNameInput(final String defaultValue, final int dialogTitle, final int buttonTitle, final Action1<String> runnable) { final Activity activity = activityRef.get(); if (activity == null) { return; @@ -187,7 +180,7 @@ public final class StoredList extends AbstractList { @Override public void call(final String input) { // remove whitespaces added by autocompletion of Android keyboard - String listName = StringUtils.trim(input); + final String listName = StringUtils.trim(input); if (StringUtils.isNotBlank(listName)) { runnable.call(listName); } @@ -225,8 +218,8 @@ public final class StoredList extends AbstractList { /** * Return the given list, if it is a concrete list. Return the default list otherwise. */ - public static int getConcreteList(int listId) { - if (listId == PseudoList.ALL_LIST.id || listId == TEMPORARY_LIST_ID || listId == PseudoList.HISTORY_LIST.id) { + public static int getConcreteList(final int listId) { + if (listId == PseudoList.ALL_LIST.id || listId == TEMPORARY_LIST.id || listId == PseudoList.HISTORY_LIST.id) { return STANDARD_LIST_ID; } return listId; diff --git a/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java b/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java index b2cb0b2..8e4b114 100644 --- a/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java +++ b/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java @@ -29,7 +29,6 @@ public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> FINDER, OWNER, MAP, - REMOVE_FROM_HISTORY, NEXT_PAGE; public int getLoaderId() { @@ -43,9 +42,9 @@ public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> private String recaptchaText = null; private SearchResult search; private boolean loading; - private CountDownLatch latch = new CountDownLatch(1); + private final CountDownLatch latch = new CountDownLatch(1); - public AbstractSearchLoader(Context context) { + public AbstractSearchLoader(final Context context) { super(context); } @@ -65,7 +64,7 @@ public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> // Unless we make a new Search the Loader framework won't deliver results. It does't do equals only identity search = new SearchResult(search); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("Error in Loader ", e); } loading = false; @@ -95,13 +94,13 @@ public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> public void waitForUser() { try { latch.await(); - } catch (InterruptedException e) { + } catch (final InterruptedException ignored) { Log.w("searchThread is not waiting for user…"); } } @Override - public void setKey(String key) { + public void setKey(final String key) { recaptchaKey = key; } @@ -125,7 +124,7 @@ public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> } @Override - public void setText(String text) { + public void setText(final String text) { recaptchaText = text; latch.countDown(); } diff --git a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java deleted file mode 100644 index e1573c9..0000000 --- a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java +++ /dev/null @@ -1,23 +0,0 @@ -package cgeo.geocaching.loaders; - -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.connector.gc.GCParser; -import cgeo.geocaching.settings.Settings; - -import android.content.Context; - -public class AddressGeocacheListLoader extends AbstractSearchLoader { - - private final String address; - - public AddressGeocacheListLoader(Context context, String address) { - super(context); - this.address = address; - } - - @Override - public SearchResult runSearch() { - return GCParser.searchByAddress(address, Settings.getCacheType(), Settings.isShowCaptcha(), this); - } - -} diff --git a/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java index c2d92bf..2549b7b 100644 --- a/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java @@ -3,9 +3,10 @@ package cgeo.geocaching.loaders; import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.capability.ISearchByCenter; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import org.eclipse.jdt.annotation.NonNull; + import rx.functions.Func1; import android.content.Context; diff --git a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java index fdb35f2..53e5de1 100644 --- a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java @@ -3,7 +3,7 @@ package cgeo.geocaching.loaders; import cgeo.geocaching.DataStore; import cgeo.geocaching.SearchResult; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import android.content.Context; @@ -11,7 +11,7 @@ import android.content.Context; public class HistoryGeocacheListLoader extends AbstractSearchLoader { private final Geopoint coords; - public HistoryGeocacheListLoader(Context context, Geopoint coords) { + public HistoryGeocacheListLoader(final Context context, final Geopoint coords) { super(context); this.coords = coords; } diff --git a/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java index 45b264f..4c3baf5 100644 --- a/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java @@ -13,7 +13,7 @@ public class KeywordGeocacheListLoader extends AbstractSearchLoader { private final @NonNull String keyword; - public KeywordGeocacheListLoader(Context context, final @NonNull String keyword) { + public KeywordGeocacheListLoader(final Context context, final @NonNull String keyword) { super(context); this.keyword = keyword; } diff --git a/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java index 05eac18..cd81619 100644 --- a/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java @@ -9,7 +9,7 @@ import android.content.Context; public class NextPageGeocacheListLoader extends AbstractSearchLoader { private final SearchResult search; - public NextPageGeocacheListLoader(Context context, SearchResult search) { + public NextPageGeocacheListLoader(final Context context, final SearchResult search) { super(context); this.search = search; } diff --git a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java index 0d5af6a..b9fbc76 100644 --- a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java @@ -3,7 +3,7 @@ package cgeo.geocaching.loaders; import cgeo.geocaching.DataStore; import cgeo.geocaching.Intents; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import android.content.Context; @@ -26,7 +26,6 @@ public class OfflineGeocacheListLoader extends AbstractSearchLoader { } /** - * @param listId * @return the bundle needed for querying the LoaderManager for the offline list with the given id */ public static Bundle getBundleForList(final int listId) { diff --git a/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java index 32fb020..47472be 100644 --- a/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java +++ b/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java @@ -9,7 +9,7 @@ import android.content.Context; public class PocketGeocacheListLoader extends AbstractSearchLoader { private final String guid; - public PocketGeocacheListLoader(Context context, String guid) { + public PocketGeocacheListLoader(final Context context, final String guid) { super(context); this.guid = guid; } diff --git a/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java b/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java deleted file mode 100644 index dc1a5df..0000000 --- a/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java +++ /dev/null @@ -1,28 +0,0 @@ -package cgeo.geocaching.loaders; - -import cgeo.geocaching.DataStore; -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.settings.Settings; - -import android.content.Context; - -public class RemoveFromHistoryLoader extends AbstractSearchLoader { - - private final String[] selected; - private final Geopoint coords; - - public RemoveFromHistoryLoader(Context context, String[] selected, Geopoint coords) { - super(context); - this.selected = selected.clone(); - this.coords = coords; - } - - @Override - public SearchResult runSearch() { - DataStore.clearVisitDate(selected); - return DataStore.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); - } - -} diff --git a/main/src/cgeo/geocaching/location/AndroidGeocoder.java b/main/src/cgeo/geocaching/location/AndroidGeocoder.java new file mode 100644 index 0000000..d0d07e8 --- /dev/null +++ b/main/src/cgeo/geocaching/location/AndroidGeocoder.java @@ -0,0 +1,82 @@ +package cgeo.geocaching.location; + +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import org.apache.commons.collections4.CollectionUtils; +import org.eclipse.jdt.annotation.NonNull; + +import rx.Observable; +import rx.functions.Func0; + +import android.content.Context; +import android.location.Address; +import android.location.Geocoder; + +import java.util.List; +import java.util.Locale; + +public class AndroidGeocoder { + private final Geocoder geocoder; + + public AndroidGeocoder(final Context context) { + geocoder = new Geocoder(context, Locale.getDefault()); + } + + /** + * Retrieve addresses from a textual location using Android geocoding API. The work happens on the network + * scheduler. + * + * @param keyword + * the location + * @return an observable containing zero or more locations + * + * @see Geocoder#getFromLocationName(String, int) + */ + public Observable<Address> getFromLocationName(@NonNull final String keyword) { + if (!Geocoder.isPresent()) { + return Observable.error(new RuntimeException("no Android geocoder")); + } + return Observable.defer(new Func0<Observable<Address>>() { + @Override + public Observable<Address> call() { + try { + return addressesToObservable(geocoder.getFromLocationName(keyword, 20)); + } catch (final Exception e) { + Log.i("Unable to use Android reverse geocoder: " + e.getMessage()); + return Observable.error(e); + } + } + }).subscribeOn(RxUtils.networkScheduler); + } + + /** + * Retrieve the physical address for coordinates. The work happens on the network scheduler. + * + * @param coords the coordinates + * @return an observable containing one location or an error + */ + public Observable<Address> getFromLocation(@NonNull final Geopoint coords) { + if (!Geocoder.isPresent()) { + return Observable.error(new RuntimeException("no Android reverse geocoder")); + } + return Observable.defer(new Func0<Observable<Address>>() { + @Override + public Observable<Address> call() { + try { + return addressesToObservable(geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1)); + } catch (final Exception e) { + Log.i("Unable to use Android reverse geocoder: " + e.getMessage()); + return Observable.error(e); + } + } + }).subscribeOn(RxUtils.networkScheduler).first(); + } + + private static Observable<Address> addressesToObservable(final List<Address> addresses) { + return CollectionUtils.isEmpty(addresses) ? + Observable.<Address>error(new RuntimeException("no result from Android geocoder")) : + Observable.from(addresses); + } + +} diff --git a/main/src/cgeo/geocaching/geopoint/DistanceParser.java b/main/src/cgeo/geocaching/location/DistanceParser.java index e3a7482..7cbc19f 100644 --- a/main/src/cgeo/geocaching/geopoint/DistanceParser.java +++ b/main/src/cgeo/geocaching/location/DistanceParser.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import cgeo.geocaching.utils.MatcherWrapper; @@ -22,7 +22,7 @@ public final class DistanceParser { * @throws NumberFormatException * if the given number is invalid */ - public static float parseDistance(String distanceText, final boolean metricUnit) + public static float parseDistance(final String distanceText, final boolean metricUnit) throws NumberFormatException { final MatcherWrapper matcher = new MatcherWrapper(pattern, distanceText); diff --git a/main/src/cgeo/geocaching/location/GCGeocoder.java b/main/src/cgeo/geocaching/location/GCGeocoder.java new file mode 100644 index 0000000..549044f --- /dev/null +++ b/main/src/cgeo/geocaching/location/GCGeocoder.java @@ -0,0 +1,65 @@ +package cgeo.geocaching.location; + +import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; + +import rx.Observable; +import rx.functions.Func0; + +import android.location.Address; + +import java.util.Locale; + +public class GCGeocoder { + + private GCGeocoder() { + // Do not instantiate + } + + /** + * Retrieve addresses from a textual location using geocaching.com geocoding API. The work happens on the network + * scheduler. + * + * @param address + * the location + * @return an observable containing zero or more locations + * + * @see android.location.Geocoder#getFromLocationName(String, int) + */ + public static Observable<Address> getFromLocationName(@NonNull final String address) { + return Observable.defer(new Func0<Observable<Address>>() { + @Override + public Observable<Address> call() { + if (!Settings.isGCConnectorActive()) { + return Observable.error(new RuntimeException("geocaching.com connector is not active")); + } + final ObjectNode response = Network.requestJSON("https://www.geocaching.com/api/geocode", new Parameters("q", address)); + if (response == null || !StringUtils.equalsIgnoreCase(response.path("status").asText(), "success")) { + return Observable.error(new RuntimeException("unable to use geocaching.com geocoder")); + } + + final JsonNode data = response.path("data"); + final Address geocodedAddress = new Address(Locale.getDefault()); + try { + geocodedAddress.setLatitude(data.get("lat").asDouble()); + geocodedAddress.setLongitude(data.get("lng").asDouble()); + geocodedAddress.setAddressLine(0, address); + return Observable.just(geocodedAddress); + } catch (final Exception e) { + Log.e("unable to decode answer from geocaching.com geocoder", e); + return Observable.error(e); + } + } + }).subscribeOn(RxUtils.networkScheduler); + } + +} diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/location/Geopoint.java index bb34114..a746a1e 100644 --- a/main/src/cgeo/geocaching/geopoint/Geopoint.java +++ b/main/src/cgeo/geocaching/location/Geopoint.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import cgeo.geocaching.ICoordinates; import cgeo.geocaching.R; @@ -53,7 +53,7 @@ public final class Geopoint implements ICoordinates, Parcelable { * if the string cannot be parsed * @see GeopointParser#parse(String) */ - public Geopoint(final String text) { + public Geopoint(@NonNull final String text) { final Geopoint parsed = GeopointParser.parse(text); latitude = parsed.latitude; longitude = parsed.longitude; @@ -97,12 +97,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Create new Geopoint from individual textual components. * - * @param latDir - * @param latDeg - * @param latDegFrac - * @param lonDir - * @param lonDeg - * @param lonDegFrac */ public Geopoint(final String latDir, final String latDeg, final String latDegFrac, final String lonDir, final String lonDeg, final String lonDegFrac) { @@ -113,14 +107,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Create new Geopoint from individual textual components. * - * @param latDir - * @param latDeg - * @param latMin - * @param latMinFrac - * @param lonDir - * @param lonDeg - * @param lonMin - * @param lonMinFrac */ public Geopoint(final String latDir, final String latDeg, final String latMin, final String latMinFrac, final String lonDir, final String lonDeg, final String lonMin, final String lonMinFrac) { @@ -131,16 +117,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Create new Geopoint from individual textual components. * - * @param latDir - * @param latDeg - * @param latMin - * @param latSec - * @param latSecFrac - * @param lonDir - * @param lonDeg - * @param lonMin - * @param lonSec - * @param lonSecFrac */ public Geopoint(final String latDir, final String latDeg, final String latMin, final String latSec, final String latSecFrac, final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) { @@ -202,8 +178,8 @@ public final class Geopoint implements ICoordinates, Parcelable { * @return An array of floats: the distance in meters, then the bearing in degrees */ private float[] pathTo(final Geopoint target) { - float[] results = new float[2]; - android.location.Location.distanceBetween(latitude, longitude, target.latitude, target.longitude, results); + final float[] results = new float[2]; + Location.distanceBetween(latitude, longitude, target.latitude, target.longitude, results); return results; } @@ -283,7 +259,7 @@ public final class Geopoint implements ICoordinates, Parcelable { * @see GeopointFormatter * @return formatted coordinates */ - public String format(GeopointFormatter.Format format) { + public String format(final GeopointFormatter.Format format) { return GeopointFormatter.format(format, this); } @@ -301,7 +277,7 @@ public final class Geopoint implements ICoordinates, Parcelable { abstract public static class GeopointException extends NumberFormatException { private static final long serialVersionUID = 1L; - protected GeopointException(String msg) { + protected GeopointException(final String msg) { super(msg); } } @@ -347,7 +323,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get latitude character (N or S). * - * @return */ public char getLatDir() { return latitude >= 0 ? 'N' : 'S'; @@ -356,7 +331,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get longitude character (E or W). * - * @return */ public char getLonDir() { return longitude >= 0 ? 'E' : 'W'; @@ -365,7 +339,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral non-negative latitude degrees. * - * @return */ public int getLatDeg() { return getDeg(latitude); @@ -374,7 +347,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral non-negative longitude degrees. * - * @return */ public int getLonDeg() { return getDeg(longitude); @@ -387,7 +359,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the latitude degrees scaled up by 10^5. * - * @return */ public int getLatDegFrac() { return getDegFrac(latitude); @@ -396,7 +367,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the longitude degrees scaled up by 10^5. * - * @return */ public int getLonDegFrac() { return getDegFrac(longitude); @@ -409,7 +379,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral latitude minutes. * - * @return */ public int getLatMin() { return getMin(latitude); @@ -418,7 +387,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral longitude minutes. * - * @return */ public int getLonMin() { return getMin(longitude); @@ -431,7 +399,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the latitude minutes scaled up by 1000. * - * @return */ public int getLatMinFrac() { return getMinFrac(latitude); @@ -440,7 +407,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the longitude minutes scaled up by 1000. * - * @return */ public int getLonMinFrac() { return getMinFrac(longitude); @@ -453,7 +419,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the latitude minutes. * - * @return */ public double getLatMinRaw() { return getMinRaw(latitude); @@ -462,7 +427,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the longitude minutes. * - * @return */ public double getLonMinRaw() { return getMinRaw(longitude); @@ -475,7 +439,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral part of the latitude seconds. * - * @return */ public int getLatSec() { return getSec(latitude); @@ -484,7 +447,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the integral part of the longitude seconds. * - * @return */ public int getLonSec() { return getSec(longitude); @@ -497,7 +459,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the latitude seconds scaled up by 1000. * - * @return */ public int getLatSecFrac() { @@ -507,7 +468,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the fractional part of the longitude seconds scaled up by 1000. * - * @return */ public int getLonSecFrac() { @@ -521,7 +481,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the latitude seconds. * - * @return */ public double getLatSecRaw() { return getSecRaw(latitude); @@ -530,7 +489,6 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Get the longitude seconds. * - * @return */ public double getLonSecRaw() { return getSecRaw(longitude); @@ -555,19 +513,19 @@ public final class Geopoint implements ICoordinates, Parcelable { /** * Gets distance in meters (workaround for 4.2.1 JIT bug). */ - public static double getDistance(double lat1, double lon1, double lat2, double lon2) { + public static double getDistance(final double lat1, final double lon1, final double lat2, final double lon2) { // for haversine use R = 6372.8 km instead of 6371 km - double earthRadius = 6372.8; - double dLat = toRadians(lat2 - lat1); - double dLon = toRadians(lon2 - lon1); - double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + final double earthRadius = 6372.8; + final double dLat = toRadians(lat2 - lat1); + final double dLon = toRadians(lon2 - lon1); + final double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); // simplify haversine return (2 * earthRadius * 1000 * Math.asin(Math.sqrt(a))); } - private static double toRadians(double angdeg) { + private static double toRadians(final double angdeg) { return angdeg * DEG_TO_RAD; } diff --git a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java b/main/src/cgeo/geocaching/location/GeopointFormatter.java index a6965f9..599b6c7 100644 --- a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java +++ b/main/src/cgeo/geocaching/location/GeopointFormatter.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import java.util.Locale; diff --git a/main/src/cgeo/geocaching/geopoint/GeopointParser.java b/main/src/cgeo/geocaching/location/GeopointParser.java index b486f01..273c5b8 100644 --- a/main/src/cgeo/geocaching/geopoint/GeopointParser.java +++ b/main/src/cgeo/geocaching/location/GeopointParser.java @@ -1,9 +1,9 @@ -package cgeo.geocaching.geopoint; - +package cgeo.geocaching.location; import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import java.util.regex.Pattern; @@ -17,16 +17,16 @@ class GeopointParser { final int matcherPos; final int matcherLength; - public ResultWrapper(final double result, int matcherPos, int stringLength) { + public ResultWrapper(final double result, final int matcherPos, final int stringLength) { this.result = result; this.matcherPos = matcherPos; this.matcherLength = stringLength; } } - // ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) - private static final Pattern PATTERN_LAT = Pattern.compile("\\b([NS]|)\\s*(\\d+)°?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_LON = Pattern.compile("\\b([WE]|)\\s*(\\d+)°?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE); + // ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) + private static final Pattern PATTERN_LAT = Pattern.compile("\\b([NS]|)\\s*(\\d+°?|°)(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE); + private static final Pattern PATTERN_LON = Pattern.compile("\\b([WE]|)\\s*(\\d+°?|°)(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE); private static final Pattern PATTERN_BAD_BLANK = Pattern.compile("(\\d)[,.] (\\d{2,})"); @@ -55,7 +55,7 @@ class GeopointParser { * @throws Geopoint.ParseException * if lat or lon could not be parsed */ - public static Geopoint parse(final String text) { + public static Geopoint parse(@NonNull final String text) { final ResultWrapper latitudeWrapper = parseHelper(text, LatLon.LAT); // cut away the latitude part when parsing the longitude final ResultWrapper longitudeWrapper = parseHelper(text.substring(latitudeWrapper.matcherPos + latitudeWrapper.matcherLength), LatLon.LON); @@ -78,55 +78,58 @@ class GeopointParser { /** * Helper for coordinates-parsing * - * @param text - * @param latlon - * @return + * @param text the text to parse + * @param latlon the kind of coordinate to parse + * @return a wrapper with the result and the corresponding matching part + * @throws Geopoint.ParseException if the text cannot be parsed */ - private static ResultWrapper parseHelper(final String text, final LatLon latlon) { - + private static ResultWrapper parseHelper(@NonNull final String text, final LatLon latlon) { MatcherWrapper matcher = new MatcherWrapper(PATTERN_BAD_BLANK, text); - String replaceSpaceAfterComma = matcher.replaceAll("$1.$2"); + final String replaceSpaceAfterComma = matcher.replaceAll("$1.$2"); final Pattern pattern = LatLon.LAT == latlon ? PATTERN_LAT : PATTERN_LON; matcher = new MatcherWrapper(pattern, replaceSpaceAfterComma); try { return new ResultWrapper(Double.valueOf(replaceSpaceAfterComma), 0, text.length()); - } catch (NumberFormatException e1) { + } catch (final NumberFormatException ignored) { // fall through to advanced parsing } - if (matcher.find()) { - final double sign = matcher.group(1).equalsIgnoreCase("S") || matcher.group(1).equalsIgnoreCase("W") ? -1.0 : 1.0; - final double degree = Integer.valueOf(matcher.group(2)).doubleValue(); + try { + if (matcher.find()) { + final double sign = matcher.group(1).equalsIgnoreCase("S") || matcher.group(1).equalsIgnoreCase("W") ? -1.0 : 1.0; + final double degree = Integer.valueOf(StringUtils.defaultIfEmpty(StringUtils.stripEnd(matcher.group(2), "°"), "0")).doubleValue(); - double minutes = 0.0; - double seconds = 0.0; + double minutes = 0.0; + double seconds = 0.0; - if (null != matcher.group(3)) { - minutes = Integer.valueOf(matcher.group(3)).doubleValue(); + if (null != matcher.group(3)) { + minutes = Integer.valueOf(matcher.group(3)).doubleValue(); - if (null != matcher.group(4)) { - seconds = Double.parseDouble("0." + matcher.group(4)) * 60.0; - } else if (null != matcher.group(5)) { - seconds = Double.parseDouble(matcher.group(5).replace(",", ".")); + if (null != matcher.group(4)) { + seconds = Double.parseDouble("0." + matcher.group(4)) * 60.0; + } else if (null != matcher.group(5)) { + seconds = Double.parseDouble(matcher.group(5).replace(",", ".")); + } } - } - - return new ResultWrapper(sign * (degree + minutes / 60.0 + seconds / 3600.0), matcher.start(), matcher.group().length()); + return new ResultWrapper(sign * (degree + minutes / 60.0 + seconds / 3600.0), matcher.start(), matcher.group().length()); + } + } catch (final NumberFormatException ignored) { + // We might have encountered too large a number. This was not the right way to do it, try another. } // Nothing found with "N 52...", try to match string as decimal degree parts (i.e. multiple doubles) try { - final String[] items = StringUtils.split(text.trim()); + final String[] items = StringUtils.split(StringUtils.trimToEmpty(text)); if (items.length > 0 && items.length <= 2) { final int index = (latlon == LatLon.LON ? items.length - 1 : 0); final String textPart = items[index]; final int pos = (latlon == LatLon.LON ? text.lastIndexOf(textPart) : text.indexOf(textPart)); return new ResultWrapper(Double.parseDouble(textPart), pos, textPart.length()); } - } catch (NumberFormatException e) { + } catch (final NumberFormatException ignored) { // The right exception will be raised below. } diff --git a/main/src/cgeo/geocaching/geopoint/IConversion.java b/main/src/cgeo/geocaching/location/IConversion.java index b1cbffd..f7f0e36 100644 --- a/main/src/cgeo/geocaching/geopoint/IConversion.java +++ b/main/src/cgeo/geocaching/location/IConversion.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; public interface IConversion { public static final float MILES_TO_KILOMETER = 1.609344f; diff --git a/main/src/cgeo/geocaching/location/MapQuestGeocoder.java b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java new file mode 100644 index 0000000..ae82546 --- /dev/null +++ b/main/src/cgeo/geocaching/location/MapQuestGeocoder.java @@ -0,0 +1,135 @@ +package cgeo.geocaching.location; + +import cgeo.geocaching.network.Network; +import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; + +import rx.Observable; +import rx.Observable.OnSubscribe; +import rx.Subscriber; +import rx.functions.Func0; + +import android.location.Address; + +import java.util.Locale; + +public class MapQuestGeocoder { + + private static final String MAPQUEST_KEY = "Fmjtd|luurn1u2n9,bs=o5-9wynua"; + + private MapQuestGeocoder() { + // Do not instantiate + } + + /** + * Retrieve addresses from a textual location using MapQuest geocoding API. The work happens on the network + * scheduler. + * + * @param address + * the location + * @return an observable containing zero or more locations + * + * @see android.location.Geocoder#getFromLocationName(String, int) + */ + public static Observable<Address> getFromLocationName(@NonNull final String address) { + return get("address", new Parameters("location", address, "maxResults", "20", "thumbMaps", "false")); + } + + /** + * Retrieve the physical address for coordinates. The work happens on the network scheduler. + * + * @param coords the coordinates + * @return an observable containing one location or an error + */ + public static Observable<Address> getFromLocation(@NonNull final Geopoint coords) { + return get("reverse", new Parameters("location", String.format(Locale.US, "%f,%f", coords.getLatitude(), coords.getLongitude()))).first(); + } + + private static Observable<Address> get(@NonNull final String method, @NonNull final Parameters parameters) { + return Observable.defer(new Func0<Observable<Address>>() { + @Override + public Observable<Address> call() { + final ObjectNode response = Network.requestJSON("https://open.mapquestapi.com/geocoding/v1/" + method, + parameters.put("key", MAPQUEST_KEY)); + if (response == null) { + Log.w("MapQuest decoder error: no response"); + return Observable.error(new RuntimeException("no answer from MapQuest geocoder")); + } + final int statusCode = response.path("info").path("statuscode").asInt(-1); + if (statusCode != 0) { + Log.w("MapQuest decoder error: statuscode is not 0"); + return Observable.error(new RuntimeException("no correct answer from MapQuest geocoder")); + } + return Observable.create(new OnSubscribe<Address>() { + @Override + public void call(final Subscriber<? super Address> subscriber) { + try { + for (final JsonNode address: response.get("results").get(0).get("locations")) { + subscriber.onNext(mapquestToAddress(address)); + } + subscriber.onCompleted(); + } catch (final Exception e) { + Log.e("Error decoding MapQuest address", e); + subscriber.onError(e); + } + } + }); + } + }).subscribeOn(RxUtils.networkScheduler); + } + + private static Address mapquestToAddress(final JsonNode mapquestAddress) { + final Address address = new Address(Locale.getDefault()); + for (int i = 1; i <= 6; i++) { + final String adminAreaName = "adminArea" + i; + setComponent(address, mapquestAddress, adminAreaName, mapquestAddress.path(adminAreaName + "Type").asText()); + } + setComponent(address, mapquestAddress, "postalCode", "PostalCode"); + int index = 0; + for (final String addressComponent: new String[]{ mapquestAddress.path("street").asText(), address.getSubLocality(), address.getLocality(), + address.getPostalCode(), address.getSubAdminArea(), address.getAdminArea(), address.getCountryCode() }) { + if (StringUtils.isNotBlank(addressComponent)) { + address.setAddressLine(index++, addressComponent); + } + } + address.setLatitude(mapquestAddress.get("latLng").get("lat").asDouble()); + address.setLongitude(mapquestAddress.get("latLng").get("lng").asDouble()); + return address; + } + + private static void setComponent(final Address address, final JsonNode mapquestAddress, final String adminArea, final String adminAreaType) { + final String content = StringUtils.trimToNull(mapquestAddress.path(adminArea).asText()); + switch (adminAreaType) { + case "City": + address.setLocality(content); + break; + case "Neighborhood": + address.setSubLocality(content); + break; + case "PostalCode": + address.setPostalCode(content); + break; + case "State": + address.setAdminArea(content); + break; + case "County": + address.setSubAdminArea(content); + break; + case "Country": + address.setCountryCode(content); + address.setCountryName(new Locale("", content).getDisplayCountry()); + break; + // Make checkers happy + default: + break; + } + } + +} diff --git a/main/src/cgeo/geocaching/geopoint/Units.java b/main/src/cgeo/geocaching/location/Units.java index 018216d..842bd83 100644 --- a/main/src/cgeo/geocaching/geopoint/Units.java +++ b/main/src/cgeo/geocaching/location/Units.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import cgeo.geocaching.settings.Settings; @@ -10,8 +10,8 @@ public class Units { public static ImmutablePair<Double, String> scaleDistance(final double distanceKilometers) { double distance; - String units; - if (Settings.isUseImperialUnits()) { + final String units; + if (Settings.useImperialUnits()) { distance = distanceKilometers / IConversion.MILES_TO_KILOMETER; if (distance >= 0.1) { units = "mi"; @@ -37,24 +37,24 @@ public class Units { } final ImmutablePair<Double, String> scaled = scaleDistance(distanceKilometers); - String formatString; + final String formatString; if (scaled.left >= 100) { - formatString = "%.0f"; + formatString = "%.0f %s"; } else if (scaled.left >= 10) { - formatString = "%.1f"; + formatString = "%.1f %s"; } else { - formatString = "%.2f"; + formatString = "%.2f %s"; } - return String.format(formatString + " %s", scaled.left, scaled.right); + return String.format(formatString, scaled.left, scaled.right); } - public static String getDistanceFromMeters(float meters) { + public static String getDistanceFromMeters(final float meters) { return getDistanceFromKilometers(meters / 1000f); } public static String getSpeed(final float kilometersPerHour) { - if (Settings.isUseImperialUnits()) { + if (Settings.useImperialUnits()) { return String.format(Locale.US, "%.0f mph", kilometersPerHour / IConversion.MILES_TO_KILOMETER); } return String.format(Locale.US, "%.0f km/h", kilometersPerHour); diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/location/Viewport.java index ba0e040..b885336 100644 --- a/main/src/cgeo/geocaching/geopoint/Viewport.java +++ b/main/src/cgeo/geocaching/location/Viewport.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import cgeo.geocaching.ICoordinates; @@ -79,6 +79,22 @@ public final class Viewport { && coords.getLatitudeE6() <= topRight.getLatitudeE6(); } + /** + * Count the number of points present in the viewport. + * + * @param points a collection of (possibly null) points + * @return the number of non-null points in the viewport + */ + public int count(final @NonNull Collection<? extends ICoordinates> points) { + int total = 0; + for (final ICoordinates point: points) { + if (point != null && contains(point)) { + total += 1; + } + } + return total; + } + @Override public String toString() { return "(" + bottomLeft.toString() + "," + topRight.toString() + ")"; @@ -86,7 +102,7 @@ public final class Viewport { /** * Check whether another viewport is fully included into the current one. - * + * * @param vp * the other viewport * @return true if the viewport is fully included into this one, false otherwise @@ -102,6 +118,7 @@ public final class Viewport { * the database table to use as prefix, or null if no prefix is required * @return the string without the "where" keyword */ + @NonNull public StringBuilder sqlWhere(@Nullable final String dbTable) { final String prefix = dbTable == null ? "" : (dbTable + "."); return new StringBuilder(prefix).append("latitude >= ").append(getLatitudeMin()).append(" and ") diff --git a/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java b/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java index 747618b..9436b2a 100644 --- a/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java +++ b/main/src/cgeo/geocaching/maps/AbstractItemizedOverlay.java @@ -17,9 +17,9 @@ import android.graphics.drawable.Drawable; */ public abstract class AbstractItemizedOverlay implements GeneralOverlay { - private ItemizedOverlayImpl ovlImpl; + private final ItemizedOverlayImpl ovlImpl; - protected AbstractItemizedOverlay(ItemizedOverlayImpl ovlImplIn) { + protected AbstractItemizedOverlay(final ItemizedOverlayImpl ovlImplIn) { ovlImpl = ovlImplIn; } @@ -27,26 +27,26 @@ public abstract class AbstractItemizedOverlay implements GeneralOverlay { ovlImpl.superPopulate(); } - public boolean onTap(int index) { + public boolean onTap(final int index) { return ovlImpl.superOnTap(index); } - Drawable boundCenterBottom(Drawable markerIn) { + Drawable boundCenterBottom(final Drawable markerIn) { return ovlImpl.superBoundCenterBottom(markerIn); } - void setLastFocusedItemIndex(int index) { + void setLastFocusedItemIndex(final int index) { ovlImpl.superSetLastFocusedItemIndex(index); } @Override - public void draw(Canvas canvas, MapViewImpl mapView, boolean shadow) { + public void draw(final Canvas canvas, final MapViewImpl mapView, final boolean shadow) { ovlImpl.superDraw(canvas, mapView, shadow); } @Override - public void drawOverlayBitmap(Canvas canvas, Point drawPosition, - MapProjectionImpl projection, byte drawZoomLevel) { + public void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final MapProjectionImpl projection, final byte drawZoomLevel) { ovlImpl.superDrawOverlayBitmap(canvas, drawPosition, projection, drawZoomLevel); } diff --git a/main/src/cgeo/geocaching/maps/AbstractMap.java b/main/src/cgeo/geocaching/maps/AbstractMap.java index 2eceadb..f62fb3a 100644 --- a/main/src/cgeo/geocaching/maps/AbstractMap.java +++ b/main/src/cgeo/geocaching/maps/AbstractMap.java @@ -19,7 +19,7 @@ public abstract class AbstractMap { MapActivityImpl mapActivity; - protected AbstractMap(MapActivityImpl activity) { + protected AbstractMap(final MapActivityImpl activity) { mapActivity = activity; } @@ -31,10 +31,10 @@ public abstract class AbstractMap { return mapActivity.getActivity(); } - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { mapActivity.superOnCreate(savedInstanceState); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { mapActivity.getActivity().requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); } } @@ -55,17 +55,17 @@ public abstract class AbstractMap { mapActivity.superOnDestroy(); } - public boolean onCreateOptionsMenu(Menu menu) { + public boolean onCreateOptionsMenu(final Menu menu) { final boolean result = mapActivity.superOnCreateOptionsMenu(menu); mapActivity.getActivity().getMenuInflater().inflate(R.menu.map_activity, menu); return result; } - public boolean onPrepareOptionsMenu(Menu menu) { + public boolean onPrepareOptionsMenu(final Menu menu) { return mapActivity.superOnPrepareOptionsMenu(menu); } - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { return mapActivity.superOnOptionsItemSelected(item); } diff --git a/main/src/cgeo/geocaching/maps/AbstractMapProvider.java b/main/src/cgeo/geocaching/maps/AbstractMapProvider.java index 620b953..bd42223 100644 --- a/main/src/cgeo/geocaching/maps/AbstractMapProvider.java +++ b/main/src/cgeo/geocaching/maps/AbstractMapProvider.java @@ -6,7 +6,7 @@ import cgeo.geocaching.maps.interfaces.MapSource; public abstract class AbstractMapProvider implements MapProvider { @Override - public void registerMapSource(MapSource mapSource) { + public void registerMapSource(final MapSource mapSource) { MapProviderFactory.registerMapSource(mapSource); } } diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 9bbf7af..42e41b1 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -4,8 +4,10 @@ import butterknife.ButterKnife; import cgeo.geocaching.CacheListActivity; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.CompassActivity; import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; +import cgeo.geocaching.Intents; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Waypoint; @@ -15,13 +17,12 @@ import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.connector.gc.MapTokens; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapActivityImpl; @@ -31,13 +32,15 @@ import cgeo.geocaching.maps.interfaces.MapProvider; import cgeo.geocaching.maps.interfaces.MapSource; import cgeo.geocaching.maps.interfaces.MapViewImpl; import cgeo.geocaching.maps.interfaces.OnMapDragListener; -import cgeo.geocaching.sensors.DirectionProvider; +import cgeo.geocaching.network.AndroidBeam; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.dialog.LiveMapInfoDialogBuilder; import cgeo.geocaching.utils.AngleUtils; import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.LeastRecentlyUsedSet; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MapUtils; @@ -45,6 +48,7 @@ import cgeo.geocaching.utils.MapUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.Subscription; import rx.functions.Action0; @@ -61,11 +65,13 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.location.Location; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; @@ -123,16 +129,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { private static final int UPDATE_PROGRESS = 0; private static final int FINISHED_LOADING_DETAILS = 1; - //Menu - private static final String EXTRAS_GEOCODE = "geocode"; - private static final String EXTRAS_COORDS = "coords"; - private static final String EXTRAS_WPTTYPE = "wpttype"; - private static final String EXTRAS_MAPSTATE = "mapstate"; - private static final String EXTRAS_SEARCH = "search"; - private static final String EXTRAS_MAP_TITLE = "mapTitle"; - private static final String EXTRAS_MAP_MODE = "mapMode"; - private static final String EXTRAS_LIVE_ENABLED = "liveEnabled"; - private static final String BUNDLE_MAP_SOURCE = "mapSource"; private static final String BUNDLE_MAP_STATE = "mapState"; private static final String BUNDLE_LIVE_ENABLED = "liveEnabled"; @@ -141,15 +137,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory { // Those are initialized in onCreate() and will never be null afterwards private Resources res; private Activity activity; - private CgeoApplication app; private MapItemFactory mapItemFactory; private String mapTitle; - private LeastRecentlyUsedSet<Geocache> caches; + final private LeastRecentlyUsedSet<Geocache> caches = new LeastRecentlyUsedSet<>(MAX_CACHES + DataStore.getAllCachesCount()); private MapViewImpl mapView; private CachesOverlay overlayCaches; private PositionAndScaleOverlay overlayPositionAndScale; - final private GeoDirHandler geoDirUpdate; + final private GeoDirHandler geoDirUpdate = new UpdateLoc(this); private SearchResult searchIntent = null; private String geocodeIntent = null; private Geopoint coordsIntent = null; @@ -161,7 +156,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { private MapTokens tokens = null; private boolean noMapTokenShowed = false; // map status data - private boolean followMyLocation = false; + private static boolean followMyLocation = true; // threads private Subscription loadTimer; private LoadDetails loadDetailsThread = null; @@ -191,19 +186,20 @@ public class CGeoMap extends AbstractMap implements ViewFactory { private boolean centered = false; // if map is already centered private boolean alreadyCentered = false; // -""- for setting my location private static final Set<String> dirtyCaches = new HashSet<>(); + // flag for honeycomb special popup menu handling + private boolean honeycombMenu = false; /** * if live map is enabled, this is the minimum zoom level, independent of the stored setting */ private static final int MIN_LIVEMAP_ZOOM = 12; // Thread pooling - private static BlockingQueue<Runnable> displayQueue = new ArrayBlockingQueue<>(1); - private static ThreadPoolExecutor displayExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, displayQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); - private static BlockingQueue<Runnable> downloadQueue = new ArrayBlockingQueue<>(1); - private static ThreadPoolExecutor downloadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, downloadQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); - private static BlockingQueue<Runnable> loadQueue = new ArrayBlockingQueue<>(1); - - private static ThreadPoolExecutor loadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, loadQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); + private static final BlockingQueue<Runnable> displayQueue = new ArrayBlockingQueue<>(1); + private static final ThreadPoolExecutor displayExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, displayQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); + private static final BlockingQueue<Runnable> downloadQueue = new ArrayBlockingQueue<>(1); + private static final ThreadPoolExecutor downloadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, downloadQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); + private static final BlockingQueue<Runnable> loadQueue = new ArrayBlockingQueue<>(1); + private static final ThreadPoolExecutor loadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, loadQueue, new ThreadPoolExecutor.DiscardOldestPolicy()); // handlers /** Updates the titles */ @@ -224,29 +220,9 @@ public class CGeoMap extends AbstractMap implements ViewFactory { switch (what) { case UPDATE_TITLE: - // set title - final StringBuilder title = new StringBuilder(); - - if (map.mapMode == MapMode.LIVE && map.isLiveEnabled) { - title.append(map.res.getString(R.string.map_live)); - } else { - title.append(map.mapTitle); - } - - map.countVisibleCaches(); - if (!map.caches.isEmpty() && !map.mapTitle.contains("[")) { - title.append(" [").append(map.cachesCnt); - if (map.cachesCnt != map.caches.size()) { - title.append('/').append(map.caches.size()); - } - title.append(']'); - } + map.setTitle(); + map.setSubtitle(); - if (Settings.isDebug() && map.lastSearchResult != null && StringUtils.isNotBlank(map.lastSearchResult.getUrl())) { - title.append('[').append(map.lastSearchResult.getUrl()).append(']'); - } - - map.setTitle(title.toString()); break; case INVALIDATE_MAP: map.mapView.repaintRequired(null); @@ -261,7 +237,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory { final private Handler displayHandler = new DisplayHandler(this); - private void setTitle(final String title) { + private void setTitle() { + final String title = calculateTitle(); /* Compatibility for the old Action Bar, only used by the maps activity at the moment */ final TextView titleview = ButterKnife.findById(activity, R.id.actionbar_title); if (titleview != null) { @@ -273,10 +250,84 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } } + private String calculateTitle() { + if (isLiveEnabled) { + return res.getString(R.string.map_live); + } + if (mapMode == MapMode.SINGLE) { + final Geocache cache = getSingleModeCache(); + if (cache != null) { + return cache.getName(); + } + } + return StringUtils.defaultIfEmpty(mapTitle, res.getString(R.string.map_map)); + } + + @Nullable + private Geocache getSingleModeCache() { + // use a copy of the caches list to avoid concurrent modification + for (final Geocache geocache : new ArrayList<>(caches)) { + if (geocache.getGeocode().equals(geocodeIntent)) { + return geocache; + } + } + return null; + } + + private void setSubtitle() { + final String subtitle = calculateSubtitle(); + if (StringUtils.isEmpty(subtitle)) { + return; + } + + /* Compatibility for the old Action Bar, only used by the maps activity at the moment */ + final TextView titleView = ButterKnife.findById(activity, R.id.actionbar_title); + if (titleView != null) { + titleView.setText(titleView.getText().toString() + ' ' + subtitle); + } + if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)) { + setSubtitleIceCreamSandwich(subtitle); + } + } + + private String calculateSubtitle() { + // count caches in the sub title + countVisibleCaches(); + final StringBuilder subtitle = new StringBuilder(); + if (!isLiveEnabled && mapMode == MapMode.SINGLE) { + final Geocache cache = getSingleModeCache(); + if (cache != null) { + return Formatter.formatMapSubtitle(cache); + } + } + if (!caches.isEmpty()) { + final int totalCount = caches.size(); + + if (cachesCnt != totalCount && Settings.isDebug()) { + subtitle.append(cachesCnt).append('/').append(res.getQuantityString(R.plurals.cache_counts, totalCount, totalCount)); + } + else { + subtitle.append(res.getQuantityString(R.plurals.cache_counts, cachesCnt, cachesCnt)); + } + } + + if (Settings.isDebug() && lastSearchResult != null && StringUtils.isNotBlank(lastSearchResult.getUrl())) { + subtitle.append(" [").append(lastSearchResult.getUrl()).append(']'); + } + + return subtitle.toString(); + } + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) private void setTitleIceCreamSandwich(final String title) { activity.getActionBar().setTitle(title); } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private void setSubtitleIceCreamSandwich(final String subtitle) { + activity.getActionBar().setSubtitle(subtitle); + } + /** Updates the progress. */ private static final class ShowProgressHandler extends Handler { private int counter = 0; @@ -331,7 +382,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { if (msg.what == UPDATE_PROGRESS) { if (waitDialog != null) { final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); - int secondsRemaining; + final int secondsRemaining; if (detailProgress > 0) { secondsRemaining = (detailTotal - detailProgress) * secondsElapsed / detailProgress; } else { @@ -367,25 +418,10 @@ public class CGeoMap extends AbstractMap implements ViewFactory { public CGeoMap(final MapActivityImpl activity) { super(activity); - geoDirUpdate = new UpdateLoc(this); } protected void countVisibleCaches() { - final List<Geocache> protectedCaches = caches.getAsList(); - - int count = 0; - if (!protectedCaches.isEmpty()) { - final Viewport viewport = mapView.getViewport(); - - for (final Geocache cache : protectedCaches) { - if (cache != null && cache.getCoords() != null) { - if (viewport.contains(cache)) { - count++; - } - } - } - } - cachesCnt = count; + cachesCnt = mapView.getViewport().count(caches.getAsList()); } @Override @@ -404,10 +440,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { // class init res = this.getResources(); activity = this.getActivity(); - app = (CgeoApplication) activity.getApplication(); - - final int countBubbleCnt = DataStore.getAllCachesCount(); - caches = new LeastRecentlyUsedSet<>(MAX_CACHES + countBubbleCnt); final MapProvider mapProvider = Settings.getMapProvider(); mapItemFactory = mapProvider.getMapItemFactory(); @@ -415,14 +447,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory { // Get parameters from the intent final Bundle extras = activity.getIntent().getExtras(); if (extras != null) { - mapMode = (MapMode) extras.get(EXTRAS_MAP_MODE); - isLiveEnabled = extras.getBoolean(EXTRAS_LIVE_ENABLED, false); - searchIntent = extras.getParcelable(EXTRAS_SEARCH); - geocodeIntent = extras.getString(EXTRAS_GEOCODE); - coordsIntent = extras.getParcelable(EXTRAS_COORDS); - waypointTypeIntent = WaypointType.findById(extras.getString(EXTRAS_WPTTYPE)); - mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE); - mapTitle = extras.getString(EXTRAS_MAP_TITLE); + mapMode = (MapMode) extras.get(Intents.EXTRA_MAP_MODE); + isLiveEnabled = extras.getBoolean(Intents.EXTRA_LIVE_ENABLED, false); + searchIntent = extras.getParcelable(Intents.EXTRA_SEARCH); + geocodeIntent = extras.getString(Intents.EXTRA_GEOCODE); + coordsIntent = extras.getParcelable(Intents.EXTRA_COORDS); + waypointTypeIntent = WaypointType.findById(extras.getString(Intents.EXTRA_WPTTYPE)); + mapStateIntent = extras.getIntArray(Intents.EXTRA_MAPSTATE); + mapTitle = extras.getString(Intents.EXTRA_TITLE); } else { mapMode = MapMode.LIVE; @@ -461,7 +493,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { activity.getActionBar().setDisplayHomeAsUpEnabled(true); } activity.setContentView(mapProvider.getMapLayoutId()); - setTitle(res.getString(R.string.map_map)); + setTitle(); // initialize map mapView = (MapViewImpl) activity.findViewById(mapProvider.getMapViewId()); @@ -475,18 +507,21 @@ public class CGeoMap extends AbstractMap implements ViewFactory { mapView.clearOverlays(); overlayCaches = mapView.createAddMapOverlay(mapView.getContext(), getResources().getDrawable(R.drawable.marker)); - overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(); + + + overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(coordsIntent, geocodeIntent); if (trailHistory != null) { overlayPositionAndScale.setHistory(trailHistory); } + mapView.repaintRequired(null); - setZoom(Settings.getMapZoom()); + setZoom(Settings.getMapZoom(mapMode)); mapView.getMapController().setCenter(Settings.getMapCenter()); if (null == mapStateIntent) { - followMyLocation = mapMode == MapMode.LIVE; + followMyLocation = followMyLocation && (mapMode == MapMode.LIVE); } else { followMyLocation = 1 == mapStateIntent[3]; if ((overlayCaches.getCircles() ? 1 : 0) != mapStateIntent[4]) { @@ -504,9 +539,22 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } prepareFilterBar(); - if (!app.isLiveMapHintShownInThisSession() && !Settings.getHideLiveMapHint() && Settings.getLiveMapHintShowCount() <= 3) { + // Check for Honeycomb fake overflow button and attach popup + final View overflowActionBar = ButterKnife.findById(activity, R.id.overflowActionBar); + if (overflowActionBar != null) { + honeycombMenu = true; + overflowActionBar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + showPopupHoneycomb(v); + } + }); + } + + if (!CgeoApplication.getInstance().isLiveMapHintShownInThisSession() && Settings.getLiveMapHintShowCount() <= 3) { LiveMapInfoDialogBuilder.create(activity).show(); } + AndroidBeam.disable(activity); } private void initMyLocationSwitchButton(final CheckBox locSwitch) { @@ -522,7 +570,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { /** * Set the zoom of the map. The zoom is restricted to a certain minimum in case of live map. * - * @param zoom */ private void setZoom(final int zoom) { mapView.getMapController().setZoom(isLiveEnabled ? Math.max(zoom, MIN_LIVEMAP_ZOOM) : zoom); @@ -546,18 +593,28 @@ public class CGeoMap extends AbstractMap implements ViewFactory { resumeSubscription = Subscriptions.from(geoDirUpdate.start(GeoDirHandler.UPDATE_GEODIR), startTimer()); if (!CollectionUtils.isEmpty(dirtyCaches)) { - for (final String geocode : dirtyCaches) { - final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); - if (cache != null) { - // new collection type needs to remove first - caches.remove(cache); - // re-add to update the freshness - caches.add(cache); + new AsyncTask<Void, Void, Void>() { + @Override + public Void doInBackground(final Void... params) { + for (final String geocode : dirtyCaches) { + final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + if (cache != null) { + // new collection type needs to remove first + caches.remove(cache); + // re-add to update the freshness + caches.add(cache); + } + } + return null; } - } - dirtyCaches.clear(); - // Update display - displayExecutor.execute(new DisplayRunnable(this)); + + @Override + public void onPostExecute(final Void result) { + dirtyCaches.clear(); + // Update display + displayExecutor.execute(new DisplayRunnable(CGeoMap.this)); + } + }.execute(); } } @@ -581,10 +638,37 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void showPopupHoneycomb(final View view) { + // Inflate the core menu ourselves + final android.widget.PopupMenu popupMenu = new android.widget.PopupMenu(getActivity(), view); + final MenuInflater inflater = new MenuInflater(getActivity()); + inflater.inflate(R.menu.map_activity, popupMenu.getMenu()); + + // continue processing menu items as usual + onCreateOptionsMenu(popupMenu.getMenu()); + + onPrepareOptionsMenu(popupMenu.getMenu()); + + popupMenu.setOnMenuItemClickListener( + new android.widget.PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(final MenuItem item) { + return onOptionsItemSelected(item); + } + } + ); + // display menu + popupMenu.show(); + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public boolean onCreateOptionsMenu(final Menu menu) { // menu inflation happens in Google/Mapsforge specific classes - super.onCreateOptionsMenu(menu); + // skip it for honeycomb - handled specially in @see showPopupHoneycomb + if (!honeycombMenu) { + super.onCreateOptionsMenu(menu); + } MapProviderFactory.addMapviewMenuItems(menu); @@ -592,7 +676,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { subMenuStrategy.setHeaderTitle(res.getString(R.string.map_strategy_title)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { /* if we have an Actionbar find the my position toggle */ final MenuItem item = menu.findItem(R.id.menu_toggle_mypos); myLocSwitch = new CheckBox(activity); @@ -640,7 +724,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { item = menu.findItem(R.id.menu_theme_mode); // show theme selection item.setVisible(mapView.hasMapThemes()); - menu.findItem(R.id.menu_as_list).setVisible(!isLoading()); + menu.findItem(R.id.menu_as_list).setVisible(!isLoading() && caches.size() > 1); menu.findItem(R.id.submenu_strategy).setVisible(isLiveEnabled); @@ -657,6 +741,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory { default: // DETAILED menu.findItem(R.id.menu_strategy_detailed).setChecked(true); } + menu.findItem(R.id.menu_hint).setVisible(mapMode == MapMode.SINGLE); + menu.findItem(R.id.menu_compass).setVisible(mapMode == MapMode.SINGLE); } catch (final RuntimeException e) { Log.e("CGeoMap.onPrepareOptionsMenu", e); } @@ -685,6 +771,10 @@ public class CGeoMap extends AbstractMap implements ViewFactory { lastSearchResult = null; searchIntent = null; ActivityMixin.invalidateOptionsMenu(activity); + if (mapMode != MapMode.SINGLE) { + mapTitle = StringUtils.EMPTY; + } + updateMapTitle(); return true; case R.id.menu_store_caches: if (!isLoading()) { @@ -714,7 +804,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { public void call(final Integer selectedListId) { storeCaches(geocodes, selectedListId); } - }, true, StoredList.TEMPORARY_LIST_ID); + }, true, StoredList.TEMPORARY_LIST.id); } else { storeCaches(geocodes, StoredList.STANDARD_LIST_ID); } @@ -742,24 +832,30 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } case R.id.menu_strategy_fastest: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.FASTEST); + Settings.setLiveMapStrategy(LivemapStrategy.FASTEST); return true; } case R.id.menu_strategy_fast: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.FAST); + Settings.setLiveMapStrategy(LivemapStrategy.FAST); return true; } case R.id.menu_strategy_auto: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.AUTO); + Settings.setLiveMapStrategy(LivemapStrategy.AUTO); return true; } case R.id.menu_strategy_detailed: { item.setChecked(true); - Settings.setLiveMapStrategy(Strategy.DETAILED); + Settings.setLiveMapStrategy(LivemapStrategy.DETAILED); return true; } + case R.id.menu_hint: + menuShowHint(); + return true; + case R.id.menu_compass: + menuCompass(); + return true; default: final MapSource mapSource = MapProviderFactory.getMapSource(id); if (mapSource != null) { @@ -771,6 +867,20 @@ public class CGeoMap extends AbstractMap implements ViewFactory { return false; } + private void menuCompass() { + final Geocache cache = getSingleModeCache(); + if (cache != null) { + CompassActivity.startActivityCache(this.getActivity(), cache); + } + } + + private void menuShowHint() { + final Geocache cache = getSingleModeCache(); + if (cache != null) { + cache.showHintToast(getActivity()); + } + } + private void selectMapTheme() { final File[] themeFiles = Settings.getMapThemeFiles(); @@ -853,7 +963,12 @@ public class CGeoMap extends AbstractMap implements ViewFactory { if (restartRequired) { mapRestart(); } else if (mapView != null) { // changeMapSource can be called by onCreate() + mapStateIntent = currentMapState(); mapView.setMapSource(); + // re-center the map + centered = false; + centerMap(geocodeIntent, searchIntent, coordsIntent, mapStateIntent); + // re-build menues ActivityMixin.invalidateOptionsMenu(activity); } @@ -864,27 +979,27 @@ public class CGeoMap extends AbstractMap implements ViewFactory { * Restart the current activity with the default map source. */ private void mapRestart() { - // close old mapview - activity.finish(); - // prepare information to restart a similar view final Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass()); - mapIntent.putExtra(EXTRAS_SEARCH, searchIntent); - mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent); + mapIntent.putExtra(Intents.EXTRA_SEARCH, searchIntent); + mapIntent.putExtra(Intents.EXTRA_GEOCODE, geocodeIntent); if (coordsIntent != null) { - mapIntent.putExtra(EXTRAS_COORDS, coordsIntent); + mapIntent.putExtra(Intents.EXTRA_COORDS, coordsIntent); } - mapIntent.putExtra(EXTRAS_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null); - mapIntent.putExtra(EXTRAS_MAP_TITLE, mapTitle); - mapIntent.putExtra(EXTRAS_MAP_MODE, mapMode); - mapIntent.putExtra(EXTRAS_LIVE_ENABLED, isLiveEnabled); + mapIntent.putExtra(Intents.EXTRA_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null); + mapIntent.putExtra(Intents.EXTRA_TITLE, mapTitle); + mapIntent.putExtra(Intents.EXTRA_MAP_MODE, mapMode); + mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, isLiveEnabled); final int[] mapState = currentMapState(); if (mapState != null) { - mapIntent.putExtra(EXTRAS_MAPSTATE, mapState); + mapIntent.putExtra(Intents.EXTRA_MAPSTATE, mapState); } + // close old map + activity.finish(); + // start the new map activity.startActivity(mapIntent); } @@ -909,13 +1024,13 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } private void savePrefs() { - Settings.setMapZoom(mapView.getMapZoomLevel()); + Settings.setMapZoom(mapMode, mapView.getMapZoomLevel()); Settings.setMapCenter(mapView.getMapViewCenter()); } // Set center of map to my location if appropriate. - private void myLocationInMiddle(final IGeoData geo) { - if (followMyLocation && !geo.isPseudoLocation()) { + private void myLocationInMiddle(final GeoData geo) { + if (followMyLocation) { centerMap(geo.getCoords()); } } @@ -931,8 +1046,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { // minimum change of location in fraction of map width/height (whatever is smaller) for position overlay update private static final float MIN_LOCATION_DELTA = 0.01f; - Location currentLocation = new Location(""); - boolean locationValid = false; + Location currentLocation = Sensors.getInstance().currentGeo(); float currentHeading; private long timeLastPositionOverlayCalculation = 0; @@ -946,16 +1060,10 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } @Override - public void updateGeoDir(final IGeoData geo, final float dir) { - if (geo.isPseudoLocation()) { - locationValid = false; - } else { - locationValid = true; - - currentLocation = geo.getLocation(); - currentHeading = DirectionProvider.getDirectionNow(dir); - repaintPositionOverlay(); - } + public void updateGeoDir(final GeoData geo, final float dir) { + currentLocation = geo; + currentHeading = AngleUtils.getDirectionNow(dir); + repaintPositionOverlay(); } /** @@ -969,23 +1077,24 @@ public class CGeoMap extends AbstractMap implements ViewFactory { try { final CGeoMap map = mapRef.get(); if (map != null) { - final boolean needsRepaintForDistance = needsRepaintForDistance(); + final boolean needsRepaintForDistanceOrAccuracy = needsRepaintForDistanceOrAccuracy(); final boolean needsRepaintForHeading = needsRepaintForHeading(); - if (needsRepaintForDistance) { - if (map.followMyLocation) { + if (needsRepaintForDistanceOrAccuracy) { + if (CGeoMap.followMyLocation) { map.centerMap(new Geopoint(currentLocation)); } } - if (needsRepaintForDistance || needsRepaintForHeading) { + if (needsRepaintForDistanceOrAccuracy || needsRepaintForHeading) { + map.overlayPositionAndScale.setCoordinates(currentLocation); map.overlayPositionAndScale.setHeading(currentHeading); map.mapView.repaintRequired(map.overlayPositionAndScale); } } } catch (final RuntimeException e) { - Log.w("Failed to update location."); + Log.w("Failed to update location", e); } } } @@ -998,11 +1107,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { return Math.abs(AngleUtils.difference(currentHeading, map.overlayPositionAndScale.getHeading())) > MIN_HEADING_DELTA; } - boolean needsRepaintForDistance() { - if (!locationValid) { - return false; - } - + boolean needsRepaintForDistanceOrAccuracy() { final CGeoMap map = mapRef.get(); if (map == null) { return false; @@ -1011,6 +1116,9 @@ public class CGeoMap extends AbstractMap implements ViewFactory { float dist = Float.MAX_VALUE; if (lastLocation != null) { + if (lastLocation.getAccuracy() != currentLocation.getAccuracy()) { + return true; + } dist = currentLocation.distanceTo(lastLocation); } @@ -1028,7 +1136,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } /** - * Starts the {@link LoadTimer}. + * Starts the load timer. */ private Subscription startTimer() { @@ -1037,7 +1145,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { displayPoint(coordsIntent); loadTimer = Subscriptions.empty(); } else { - loadTimer = startLoadTimer(); + loadTimer = Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 0, 250, TimeUnit.MILLISECONDS); } return loadTimer; } @@ -1072,7 +1180,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { // update title on any change if (moved || !viewportNow.equals(previousViewport)) { - map.displayHandler.sendEmptyMessage(UPDATE_TITLE); + map.updateMapTitle(); } previousZoom = zoomNow; @@ -1094,16 +1202,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } /** - * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}. - */ - private Subscription startLoadTimer() { - return Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 0, 250, TimeUnit.MILLISECONDS); - } - - /** * get if map is loading something * - * @return */ public boolean isLoading() { return !loadTimer.isUnsubscribed() && @@ -1114,7 +1214,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { /** * Worker thread that loads caches and waypoints from the database and then spawns the {@link DownloadRunnable}. - * started by {@link LoadTimer} + * started by the load timer. */ private static class LoadRunnable extends DoRunnable { @@ -1134,7 +1234,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); loadThreadRun = System.currentTimeMillis(); - SearchResult searchResult; + final SearchResult searchResult; if (mapMode == MapMode.LIVE) { searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(mapView.getViewport(), Settings.getCacheType())); } else { @@ -1250,9 +1350,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory { //render displayExecutor.execute(new DisplayRunnable(this)); - } catch (final ThreadDeath e) { - Log.d("DownloadThread stopped"); - displayHandler.sendEmptyMessage(UPDATE_TITLE); } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress } @@ -1302,19 +1399,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory { } itemsToDisplay.add(getCacheItem(cache)); } - - overlayCaches.updateItems(itemsToDisplay); - displayHandler.sendEmptyMessage(INVALIDATE_MAP); - - } else { + } + // don't add other waypoints to overlayCaches if just one point should be displayed + if (coordsIntent == null) { overlayCaches.updateItems(itemsToDisplay); - displayHandler.sendEmptyMessage(INVALIDATE_MAP); } + displayHandler.sendEmptyMessage(INVALIDATE_MAP); - displayHandler.sendEmptyMessage(UPDATE_TITLE); - } catch (final ThreadDeath e) { - Log.d("DisplayThread stopped"); - displayHandler.sendEmptyMessage(UPDATE_TITLE); + updateMapTitle(); } finally { showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); } @@ -1327,11 +1419,15 @@ public class CGeoMap extends AbstractMap implements ViewFactory { final CachesOverlayItemImpl item = getWaypointItem(waypoint); overlayCaches.updateItems(item); displayHandler.sendEmptyMessage(INVALIDATE_MAP); - displayHandler.sendEmptyMessage(UPDATE_TITLE); + updateMapTitle(); cachesCnt = 1; } + private void updateMapTitle() { + displayHandler.sendEmptyMessage(UPDATE_TITLE); + } + private static abstract class DoRunnable implements Runnable { private final WeakReference<CGeoMap> mapRef; @@ -1538,7 +1634,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory { if (myLocSwitch != null) { myLocSwitch.setChecked(followMyLocation); if (followMyLocation) { - myLocationInMiddle(app.currentGeo()); + myLocationInMiddle(Sensors.getInstance().currentGeo()); } } } @@ -1610,42 +1706,40 @@ public class CGeoMap extends AbstractMap implements ViewFactory { public static void startActivitySearch(final Activity fromActivity, final SearchResult search, final String title) { final Intent mapIntent = newIntent(fromActivity); - mapIntent.putExtra(EXTRAS_SEARCH, search); - mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.LIST); - mapIntent.putExtra(EXTRAS_LIVE_ENABLED, false); + mapIntent.putExtra(Intents.EXTRA_SEARCH, search); + mapIntent.putExtra(Intents.EXTRA_MAP_MODE, MapMode.LIST); + mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, false); if (StringUtils.isNotBlank(title)) { - mapIntent.putExtra(CGeoMap.EXTRAS_MAP_TITLE, title); + mapIntent.putExtra(Intents.EXTRA_TITLE, title); } fromActivity.startActivity(mapIntent); } - public static void startActivityLiveMap(final Activity fromActivity) { - final Intent mapIntent = newIntent(fromActivity); - mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.LIVE); - mapIntent.putExtra(EXTRAS_LIVE_ENABLED, Settings.isLiveMap()); - fromActivity.startActivity(mapIntent); + public static Intent getLiveMapIntent(final Activity fromActivity) { + return newIntent(fromActivity) + .putExtra(Intents.EXTRA_MAP_MODE, MapMode.LIVE) + .putExtra(Intents.EXTRA_LIVE_ENABLED, Settings.isLiveMap()); } public static void startActivityCoords(final Activity fromActivity, final Geopoint coords, final WaypointType type, final String title) { final Intent mapIntent = newIntent(fromActivity); - mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.COORDS); - mapIntent.putExtra(EXTRAS_LIVE_ENABLED, false); - mapIntent.putExtra(EXTRAS_COORDS, coords); + mapIntent.putExtra(Intents.EXTRA_MAP_MODE, MapMode.COORDS); + mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, false); + mapIntent.putExtra(Intents.EXTRA_COORDS, coords); if (type != null) { - mapIntent.putExtra(EXTRAS_WPTTYPE, type.id); + mapIntent.putExtra(Intents.EXTRA_WPTTYPE, type.id); } if (StringUtils.isNotBlank(title)) { - mapIntent.putExtra(EXTRAS_MAP_TITLE, title); + mapIntent.putExtra(Intents.EXTRA_TITLE, title); } fromActivity.startActivity(mapIntent); } public static void startActivityGeoCode(final Activity fromActivity, final String geocode) { final Intent mapIntent = newIntent(fromActivity); - mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.SINGLE); - mapIntent.putExtra(EXTRAS_LIVE_ENABLED, false); - mapIntent.putExtra(EXTRAS_GEOCODE, geocode); - mapIntent.putExtra(EXTRAS_MAP_TITLE, geocode); + mapIntent.putExtra(Intents.EXTRA_MAP_MODE, MapMode.SINGLE); + mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, false); + mapIntent.putExtra(Intents.EXTRA_GEOCODE, geocode); fromActivity.startActivity(mapIntent); } diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java index 3c6109e..9649c0d 100644 --- a/main/src/cgeo/geocaching/maps/CachesOverlay.java +++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java @@ -10,7 +10,7 @@ import cgeo.geocaching.activity.Progress; import cgeo.geocaching.connector.gc.GCMap; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.ItemizedOverlayImpl; @@ -43,13 +43,13 @@ public class CachesOverlay extends AbstractItemizedOverlay { private List<CachesOverlayItemImpl> items = new ArrayList<>(); private Context context = null; private boolean displayCircles = false; - private Progress progress = new Progress(); + private final Progress progress = new Progress(); private Paint blockedCircle = null; private PaintFlagsDrawFilter setFilter = null; private PaintFlagsDrawFilter removeFilter = null; private MapItemFactory mapItemFactory = null; - public CachesOverlay(ItemizedOverlayImpl ovlImpl, Context contextIn) { + public CachesOverlay(final ItemizedOverlayImpl ovlImpl, final Context contextIn) { super(ovlImpl); populate(); @@ -60,19 +60,19 @@ public class CachesOverlay extends AbstractItemizedOverlay { mapItemFactory = mapProvider.getMapItemFactory(); } - void updateItems(CachesOverlayItemImpl item) { - List<CachesOverlayItemImpl> itemsPre = new ArrayList<>(); + void updateItems(final CachesOverlayItemImpl item) { + final List<CachesOverlayItemImpl> itemsPre = new ArrayList<>(); itemsPre.add(item); updateItems(itemsPre); } - void updateItems(List<CachesOverlayItemImpl> itemsPre) { + void updateItems(final List<CachesOverlayItemImpl> itemsPre) { if (itemsPre == null) { return; } - for (CachesOverlayItemImpl item : itemsPre) { + for (final CachesOverlayItemImpl item : itemsPre) { item.setMarker(boundCenterBottom(item.getMarker(0))); } @@ -97,7 +97,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { } @Override - public void draw(Canvas canvas, MapViewImpl mapView, boolean shadow) { + public void draw(final Canvas canvas, final MapViewImpl mapView, final boolean shadow) { drawInternal(canvas, mapView.getMapProjection()); @@ -105,15 +105,15 @@ public class CachesOverlay extends AbstractItemizedOverlay { } @Override - public void drawOverlayBitmap(Canvas canvas, Point drawPosition, - MapProjectionImpl projection, byte drawZoomLevel) { + public void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final MapProjectionImpl projection, final byte drawZoomLevel) { drawInternal(canvas, projection); super.drawOverlayBitmap(canvas, drawPosition, projection, drawZoomLevel); } - private void drawInternal(Canvas canvas, MapProjectionImpl projection) { + private void drawInternal(final Canvas canvas, final MapProjectionImpl projection) { if (!displayCircles || items.isEmpty()) { return; } @@ -129,7 +129,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { final int radius = calculateDrawingRadius(projection); final Point center = new Point(); - for (CachesOverlayItemImpl item : items) { + for (final CachesOverlayItemImpl item : items) { if (item.applyDistanceRule()) { final Geopoint itemCoord = item.getCoord().getCoords(); final GeoPointImpl itemGeo = mapItemFactory.getGeoPointBase(itemCoord); @@ -158,11 +158,9 @@ public class CachesOverlay extends AbstractItemizedOverlay { * reality and therefore the minor changes due to the projection will not make any visible difference at the zoom * levels which are used to see the circles. * - * @param projection - * @return */ - private int calculateDrawingRadius(MapProjectionImpl projection) { - float[] distanceArray = new float[1]; + private int calculateDrawingRadius(final MapProjectionImpl projection) { + final float[] distanceArray = new float[1]; final Geopoint itemCoord = items.get(0).getCoord().getCoords(); Location.distanceBetween(itemCoord.getLatitude(), itemCoord.getLongitude(), @@ -202,7 +200,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { } @Override - public boolean onTap(int index) { + public boolean onTap(final int index) { try { if (items.size() <= index) { @@ -232,7 +230,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { if (StringUtils.equalsIgnoreCase(coordType, "cache") && StringUtils.isNotBlank(coordinate.getGeocode())) { final Geocache cache = DataStore.loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); if (cache != null) { - RequestDetailsThread requestDetailsThread = new RequestDetailsThread(cache); + final RequestDetailsThread requestDetailsThread = new RequestDetailsThread(cache); if (!requestDetailsThread.requestRequired()) { // don't show popup if we have enough details progress.dismiss(); @@ -253,21 +251,19 @@ public class CachesOverlay extends AbstractItemizedOverlay { } progress.dismiss(); - } catch (NotFoundException e) { + } catch (final NotFoundException e) { Log.e("CachesOverlay.onTap", e); - if (progress != null) { - progress.dismiss(); - } + progress.dismiss(); } return true; } @Override - public CachesOverlayItemImpl createItem(int index) { + public CachesOverlayItemImpl createItem(final int index) { try { return items.get(index); - } catch (Exception e) { + } catch (final Exception e) { Log.e("CachesOverlay.createItem", e); } @@ -278,7 +274,7 @@ public class CachesOverlay extends AbstractItemizedOverlay { public int size() { try { return items.size(); - } catch (Exception e) { + } catch (final Exception e) { Log.e("CachesOverlay.size", e); } diff --git a/main/src/cgeo/geocaching/maps/DirectionDrawer.java b/main/src/cgeo/geocaching/maps/DirectionDrawer.java new file mode 100644 index 0000000..c746221 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/DirectionDrawer.java @@ -0,0 +1,60 @@ +package cgeo.geocaching.maps; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.maps.interfaces.MapItemFactory; +import cgeo.geocaching.maps.interfaces.MapProjectionImpl; +import cgeo.geocaching.settings.Settings; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.location.Location; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +public class DirectionDrawer { + private Geopoint currentCoords; + private final Geopoint destinationCoords; + private final MapItemFactory mapItemFactory; + private final float width; + + private Paint line = null; + + public DirectionDrawer(final Geopoint coords) { + this.destinationCoords = coords; + this.mapItemFactory = Settings.getMapProvider().getMapItemFactory(); + + final DisplayMetrics metrics = new DisplayMetrics(); + final WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getMetrics(metrics); + + width = 4f * metrics.density; + + } + + public void setCoordinates(final Location coordinatesIn) { + currentCoords = new Geopoint(coordinatesIn); + } + + void drawDirection(final Canvas canvas, final MapProjectionImpl projection) { + if (currentCoords == null) { + return; + } + + if (line == null) { + line = new Paint(); + line.setAntiAlias(true); + line.setStrokeWidth(width); + line.setColor(0x80EB391E); + } + + final Point pos = new Point(); + final Point dest = new Point(); + projection.toPixels(mapItemFactory.getGeoPointBase(currentCoords), pos); + projection.toPixels(mapItemFactory.getGeoPointBase(destinationCoords), dest); + + canvas.drawLine(pos.x, pos.y, dest.x, dest.y, line); + } +} diff --git a/main/src/cgeo/geocaching/maps/DistanceDrawer.java b/main/src/cgeo/geocaching/maps/DistanceDrawer.java new file mode 100644 index 0000000..9dde8e6 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/DistanceDrawer.java @@ -0,0 +1,130 @@ +package cgeo.geocaching.maps; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.maps.interfaces.MapViewImpl; + +import android.content.Context; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.location.Location; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +public class DistanceDrawer { + private final Geopoint destinationCoords; + + private Paint paintBox = null; + private Paint paintBoxShadow = null; + private Paint paintText = null; + private BlurMaskFilter blurBoxShadow = null; + + private final boolean needsInvertedColors; + private float pixelDensity = 0; + private final float boxWidth, boxHeight, boxCornerRadius, boxShadowSize, boxPadding; + private final float textHeight, maxTextWidth; + private final float boxX, boxY; + + private String distanceText = null; + + public DistanceDrawer(final MapViewImpl mapView, final Geopoint destinationCoords) { + this.destinationCoords = destinationCoords; + + final DisplayMetrics metrics = new DisplayMetrics(); + final WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getMetrics(metrics); + + pixelDensity = metrics.density; + + boxPadding = 2; + boxWidth = 100 * pixelDensity + 3 * boxPadding; + boxHeight = 30 * pixelDensity + 2 * boxPadding; + boxCornerRadius = 5 * pixelDensity; + boxShadowSize = 1 * pixelDensity; + textHeight = 20 * pixelDensity; + + needsInvertedColors = mapView.needsInvertedColors(); + boxX = metrics.widthPixels - boxWidth; + boxY = 0; + + maxTextWidth = boxWidth - 3 * boxPadding; + } + + public void setCoordinates(final Location location) { + final Geopoint currentCoords = new Geopoint(location); + + final float distance = currentCoords.distanceTo(destinationCoords); + distanceText = Units.getDistanceFromKilometers(distance); + } + + void drawDistance(final Canvas canvas) { + if (distanceText == null) { + return; + } + + if (blurBoxShadow == null) { + blurBoxShadow = new BlurMaskFilter(3, BlurMaskFilter.Blur.NORMAL); + + paintBoxShadow = new Paint(); + paintBoxShadow.setAntiAlias(true); + paintBoxShadow.setMaskFilter(blurBoxShadow); + + paintBox = new Paint(); + paintBox.setAntiAlias(true); + + paintText = new Paint(); + paintText.setAntiAlias(true); + paintText.setTextAlign(Paint.Align.LEFT); + paintText.setTypeface(Typeface.DEFAULT_BOLD); + + final int TRANSPARENCY = 0x80000000; + if (needsInvertedColors) { + paintBoxShadow.setColor(0x000000 | TRANSPARENCY); + paintBox.setColor(0xFFFFFF | TRANSPARENCY); + paintText.setColor(0xFF000000); + } else { + paintBoxShadow.setColor(0xFFFFFF | TRANSPARENCY); + paintBox.setColor(0x000000 | TRANSPARENCY); + paintText.setColor(0xFFFFFFFF); + } + } + + /* Calculate text size */ + final Rect textBounds = new Rect(); + paintText.setTextSize(textHeight); + paintText.getTextBounds(distanceText, 0, distanceText.length(), textBounds); + while (textBounds.height() > maxTextWidth) { + paintText.setTextSize(paintText.getTextSize() - 1); + paintText.getTextBounds(distanceText, 0, distanceText.length(), textBounds); + } + + final float textX = (boxWidth - 3 * boxPadding - textBounds.width()) / 2 + boxX + 2 * boxPadding; + final float textY = (boxHeight + textBounds.height()) / 2 + boxY; + + /* Paint background box */ + canvas.drawRoundRect( + new RectF( + boxX - boxShadowSize, boxY - boxShadowSize - boxCornerRadius, + boxX + boxWidth + boxShadowSize + boxCornerRadius, boxY + boxHeight + boxShadowSize + ), + boxCornerRadius, boxCornerRadius, + paintBoxShadow + ); + canvas.drawRoundRect( + new RectF( + boxX, boxY - boxCornerRadius, + boxX + boxWidth + boxCornerRadius, boxY + boxHeight + ), + boxCornerRadius, boxCornerRadius, + paintBox + ); + + /* Paint distance */ + canvas.drawText(distanceText, textX, textY, paintText); + } +} diff --git a/main/src/cgeo/geocaching/maps/LivemapStrategy.java b/main/src/cgeo/geocaching/maps/LivemapStrategy.java new file mode 100644 index 0000000..c135fc8 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/LivemapStrategy.java @@ -0,0 +1,45 @@ +package cgeo.geocaching.maps; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.R; + +import java.util.EnumSet; + +/** + * Defines the strategy for the Live Map + */ +public enum LivemapStrategy { + FASTEST(1, EnumSet.of(Flag.LOAD_TILES), R.string.map_strategy_fastest), + FAST(2, EnumSet.of(Flag.LOAD_TILES, Flag.PARSE_TILES), R.string.map_strategy_fast), + AUTO(3, EnumSet.noneOf(Flag.class), R.string.map_strategy_auto), + DETAILED(4, EnumSet.allOf(Flag.class), R.string.map_strategy_detailed); + + public final int id; + public final EnumSet<Flag> flags; + private final int stringId; + + public enum Flag { + LOAD_TILES, // 2x2 tiles filling the complete viewport + PARSE_TILES, // parse PNG images + SEARCH_NEARBY // searchByCoords() + } + + LivemapStrategy(final int id, final EnumSet<Flag> flags, final int stringId) { + this.id = id; + this.flags = flags; + this.stringId = stringId; + } + + public static LivemapStrategy getById(final int id) { + for (final LivemapStrategy strategy : LivemapStrategy.values()) { + if (strategy.id == id) { + return strategy; + } + } + return AUTO; + } + + public final String getL10n() { + return CgeoApplication.getInstance().getBaseContext().getResources().getString(stringId); + } +} diff --git a/main/src/cgeo/geocaching/maps/MapActivity.java b/main/src/cgeo/geocaching/maps/MapActivity.java new file mode 100644 index 0000000..28668ca --- /dev/null +++ b/main/src/cgeo/geocaching/maps/MapActivity.java @@ -0,0 +1,17 @@ +package cgeo.geocaching.maps; + +import android.app.Activity; +import android.os.Bundle; + +/** + * This activity provides an entry point for external intent calls, and then forwards to the currently used map activity + * implementation. + */ +public class MapActivity extends Activity { + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + startActivity(CGeoMap.getLiveMapIntent(this)); + finish(); + } +} diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java index 8685d94..b504020 100644 --- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java +++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java @@ -33,7 +33,8 @@ public class MapProviderFactory { public static boolean isGoogleMapsInstalled() { // Check if API key is available - if (StringUtils.isBlank(CgeoApplication.getInstance().getString(R.string.maps_api_key))) { + final String mapsKey = CgeoApplication.getInstance().getString(R.string.maps_api_key); + if (StringUtils.length(mapsKey) < 30 || StringUtils.contains(mapsKey, "key")) { Log.w("No Google API key available."); return false; } @@ -41,7 +42,7 @@ public class MapProviderFactory { // Check if API is available try { Class.forName("com.google.android.maps.MapActivity"); - } catch (ClassNotFoundException e) { + } catch (final ClassNotFoundException ignored) { return false; } @@ -59,7 +60,7 @@ public class MapProviderFactory { return provider1 == provider2 && provider1.isSameActivity(source1, source2); } - public static void addMapviewMenuItems(Menu menu) { + public static void addMapviewMenuItems(final Menu menu) { final SubMenu parentMenu = menu.findItem(R.id.menu_select_mapview).getSubMenu(); final int currentSource = Settings.getMapSource().getNumericalId(); @@ -78,8 +79,8 @@ public class MapProviderFactory { * @return the map source, or <tt>null</tt> if <tt>id</tt> does not correspond to a registered map source */ @Nullable - public static MapSource getMapSource(int id) { - for (MapSource mapSource : mapSources) { + public static MapSource getMapSource(final int id) { + for (final MapSource mapSource : mapSources) { if (mapSource.getNumericalId() == id) { return mapSource; } @@ -109,7 +110,7 @@ public class MapProviderFactory { */ public static void deleteOfflineMapSources() { final ArrayList<MapSource> deletion = new ArrayList<>(); - for (MapSource mapSource : mapSources) { + for (final MapSource mapSource : mapSources) { if (mapSource instanceof MapsforgeMapProvider.OfflineMapSource) { deletion.add(mapSource); } diff --git a/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java b/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java index 63fcd73..9a6e4b9 100644 --- a/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java +++ b/main/src/cgeo/geocaching/maps/PositionAndScaleOverlay.java @@ -1,5 +1,8 @@ package cgeo.geocaching.maps; +import cgeo.geocaching.DataStore; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.interfaces.GeneralOverlay; import cgeo.geocaching.maps.interfaces.MapProjectionImpl; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -16,22 +19,40 @@ public class PositionAndScaleOverlay implements GeneralOverlay { PositionDrawer positionDrawer = null; ScaleDrawer scaleDrawer = null; + DirectionDrawer directionDrawer = null; + DistanceDrawer distanceDrawer = null; - public PositionAndScaleOverlay(OverlayImpl ovlImpl) { + public PositionAndScaleOverlay(final OverlayImpl ovlImpl, final MapViewImpl mapView, final Geopoint coords, final String geocode) { this.ovlImpl = ovlImpl; positionDrawer = new PositionDrawer(); scaleDrawer = new ScaleDrawer(); + + if (coords != null) { + directionDrawer = new DirectionDrawer(coords); + distanceDrawer = new DistanceDrawer(mapView, coords); + } else if (geocode != null) { + final Viewport bounds = DataStore.getBounds(geocode); + if (bounds != null) { + directionDrawer = new DirectionDrawer(bounds.center); + distanceDrawer = new DistanceDrawer(mapView, bounds.center); + } + } } - public void setCoordinates(Location coordinatesIn) { + public void setCoordinates(final Location coordinatesIn) { positionDrawer.setCoordinates(coordinatesIn); + if (directionDrawer != null) { + directionDrawer.setCoordinates(coordinatesIn); + distanceDrawer.setCoordinates(coordinatesIn); + } + } public Location getCoordinates() { return positionDrawer.getCoordinates(); } - public void setHeading(float bearingNow) { + public void setHeading(final float bearingNow) { positionDrawer.setHeading(bearingNow); } @@ -40,21 +61,27 @@ public class PositionAndScaleOverlay implements GeneralOverlay { } @Override - public void drawOverlayBitmap(Canvas canvas, Point drawPosition, - MapProjectionImpl projection, byte drawZoomLevel) { + public void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final MapProjectionImpl projection, final byte drawZoomLevel) { drawInternal(canvas, projection, getOverlayImpl().getMapViewImpl()); } @Override - public void draw(Canvas canvas, MapViewImpl mapView, boolean shadow) { + public void draw(final Canvas canvas, final MapViewImpl mapView, final boolean shadow) { drawInternal(canvas, mapView.getMapProjection(), mapView); } - private void drawInternal(Canvas canvas, MapProjectionImpl projection, MapViewImpl mapView) { + private void drawInternal(final Canvas canvas, final MapProjectionImpl projection, final MapViewImpl mapView) { + if (directionDrawer != null) { + directionDrawer.drawDirection(canvas, projection); + } positionDrawer.drawPosition(canvas, projection); scaleDrawer.drawScale(canvas, mapView); + if (distanceDrawer != null) { + distanceDrawer.drawDistance(canvas); + } } @Override @@ -66,7 +93,7 @@ public class PositionAndScaleOverlay implements GeneralOverlay { return positionDrawer.getHistory(); } - public void setHistory(ArrayList<Location> history) { + public void setHistory(final ArrayList<Location> history) { positionDrawer.setHistory(history); } } diff --git a/main/src/cgeo/geocaching/maps/PositionDrawer.java b/main/src/cgeo/geocaching/maps/PositionDrawer.java index 08244ef..c7d1734 100644 --- a/main/src/cgeo/geocaching/maps/PositionDrawer.java +++ b/main/src/cgeo/geocaching/maps/PositionDrawer.java @@ -2,7 +2,7 @@ package cgeo.geocaching.maps; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapItemFactory; import cgeo.geocaching.maps.interfaces.MapProjectionImpl; @@ -28,21 +28,21 @@ public class PositionDrawer { private Paint accuracyCircle = null; private Paint historyLine = null; private Paint historyLineShadow = null; - private Point center = new Point(); - private Point left = new Point(); + private final Point center = new Point(); + private final Point left = new Point(); private Bitmap arrow = null; private int widthArrowHalf = 0; private int heightArrowHalf = 0; private PaintFlagsDrawFilter setfil = null; private PaintFlagsDrawFilter remfil = null; - private PositionHistory positionHistory = new PositionHistory(); - private MapItemFactory mapItemFactory; + private final PositionHistory positionHistory = new PositionHistory(); + private final MapItemFactory mapItemFactory; public PositionDrawer() { this.mapItemFactory = Settings.getMapProvider().getMapItemFactory(); } - void drawPosition(Canvas canvas, MapProjectionImpl projection) { + void drawPosition(final Canvas canvas, final MapProjectionImpl projection) { if (coordinates == null || location == null) { return; } @@ -76,20 +76,20 @@ public class PositionDrawer { canvas.setDrawFilter(setfil); - double latitude = coordinates.getLatitude(); - double longitude = coordinates.getLongitude(); - float accuracy = coordinates.getAccuracy(); + final double latitude = coordinates.getLatitude(); + final double longitude = coordinates.getLongitude(); + final float accuracy = coordinates.getAccuracy(); - float[] result = new float[1]; + final float[] result = new float[1]; Location.distanceBetween(latitude, longitude, latitude, longitude + 1, result); - float longitudeLineDistance = result[0]; + final float longitudeLineDistance = result[0]; final Geopoint leftCoords = new Geopoint(latitude, longitude - accuracy / longitudeLineDistance); - GeoPointImpl leftGeo = mapItemFactory.getGeoPointBase(leftCoords); + final GeoPointImpl leftGeo = mapItemFactory.getGeoPointBase(leftCoords); projection.toPixels(leftGeo, left); projection.toPixels(location, center); - int radius = center.x - left.x; + final int radius = center.x - left.x; accuracyCircle.setColor(0x66000000); accuracyCircle.setStyle(Style.STROKE); @@ -106,23 +106,23 @@ public class PositionDrawer { final ArrayList<Location> paintHistory = new ArrayList<>(positionHistory.getHistory()); paintHistory.add(coordinates); - int size = paintHistory.size(); + final int size = paintHistory.size(); if (size > 1) { int alphaCnt = size - 201; if (alphaCnt < 1) { alphaCnt = 1; } - Point pointNow = new Point(); - Point pointPrevious = new Point(); - Location prev = paintHistory.get(0); + final Point pointNow = new Point(); + final Point pointPrevious = new Point(); + final Location prev = paintHistory.get(0); projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), pointPrevious); for (int cnt = 1; cnt < size; cnt++) { - Location now = paintHistory.get(cnt); + final Location now = paintHistory.get(cnt); projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), pointNow); - int alpha; + final int alpha; if ((alphaCnt - cnt) > 0) { alpha = 255 / (alphaCnt - cnt); } @@ -147,10 +147,10 @@ public class PositionDrawer { heightArrowHalf = arrow.getHeight() / 2; } - int marginLeft = center.x - widthArrowHalf; - int marginTop = center.y - heightArrowHalf; + final int marginLeft = center.x - widthArrowHalf; + final int marginTop = center.y - heightArrowHalf; - Matrix matrix = new Matrix(); + final Matrix matrix = new Matrix(); matrix.setRotate(heading, widthArrowHalf, heightArrowHalf); matrix.postTranslate(marginLeft, marginTop); @@ -163,11 +163,11 @@ public class PositionDrawer { return positionHistory.getHistory(); } - public void setHistory(ArrayList<Location> history) { + public void setHistory(final ArrayList<Location> history) { positionHistory.setHistory(history); } - public void setHeading(float bearingNow) { + public void setHeading(final float bearingNow) { heading = bearingNow; } @@ -175,7 +175,7 @@ public class PositionDrawer { return heading; } - public void setCoordinates(Location coordinatesIn) { + public void setCoordinates(final Location coordinatesIn) { coordinates = coordinatesIn; location = mapItemFactory.getGeoPointBase(new Geopoint(coordinates)); } diff --git a/main/src/cgeo/geocaching/maps/PositionHistory.java b/main/src/cgeo/geocaching/maps/PositionHistory.java index af13740..4394eba 100644 --- a/main/src/cgeo/geocaching/maps/PositionHistory.java +++ b/main/src/cgeo/geocaching/maps/PositionHistory.java @@ -24,7 +24,7 @@ public class PositionHistory { /** * Adds the current position to the trail history to be able to show the trail on the map. */ - void rememberTrailPosition(Location coordinates) { + void rememberTrailPosition(final Location coordinates) { if (coordinates.getAccuracy() >= 50f) { return; } @@ -36,7 +36,7 @@ public class PositionHistory { return; } - Location historyRecent = history.get(history.size() - 1); + final Location historyRecent = history.get(history.size() - 1); if (historyRecent.distanceTo(coordinates) <= MINIMUM_DISTANCE_METERS) { return; } @@ -56,7 +56,7 @@ public class PositionHistory { return history; } - public void setHistory(ArrayList<Location> history) { + public void setHistory(final ArrayList<Location> history) { this.history = history; } diff --git a/main/src/cgeo/geocaching/maps/ScaleDrawer.java b/main/src/cgeo/geocaching/maps/ScaleDrawer.java index 95c987d..e905873 100644 --- a/main/src/cgeo/geocaching/maps/ScaleDrawer.java +++ b/main/src/cgeo/geocaching/maps/ScaleDrawer.java @@ -1,8 +1,8 @@ package cgeo.geocaching.maps; import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -25,8 +25,8 @@ public class ScaleDrawer { private float pixelDensity = 0; public ScaleDrawer() { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); + final DisplayMetrics metrics = new DisplayMetrics(); + final WindowManager windowManager = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); windowManager.getDefaultDisplay().getMetrics(metrics); pixelDensity = metrics.density; } @@ -36,7 +36,7 @@ public class ScaleDrawer { return scale * Math.floor(distance / scale); } - void drawScale(Canvas canvas, MapViewImpl mapView) { + void drawScale(final Canvas canvas, final MapViewImpl mapView) { final double span = mapView.getLongitudeSpan() / 1e6; final GeoPointImpl center = mapView.getMapViewCenter(); diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java index 3596d5f..1e69b44 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java @@ -33,5 +33,8 @@ public interface MapActivityImpl { boolean superOnOptionsItemSelected(MenuItem item); + /** + * called from the pseudo actionbar layout + */ public abstract void navigateUp(View view); } diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java b/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java index 22c6698..f69de03 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapItemFactory.java @@ -1,7 +1,7 @@ package cgeo.geocaching.maps.interfaces; import cgeo.geocaching.IWaypoint; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; public interface MapItemFactory { diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java index 4a6d733..1876dfc 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapViewImpl.java @@ -1,6 +1,7 @@ package cgeo.geocaching.maps.interfaces; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.PositionAndScaleOverlay; @@ -46,7 +47,7 @@ public interface MapViewImpl { CachesOverlay createAddMapOverlay(Context context, Drawable drawable); - PositionAndScaleOverlay createAddPositionAndScaleOverlay(); + PositionAndScaleOverlay createAddPositionAndScaleOverlay(final Geopoint coords, final String geocode); void setMapSource(); diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java index b9e40d7..02e4243 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlay.java @@ -18,10 +18,10 @@ import java.util.concurrent.locks.ReentrantLock; public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlayItem> implements ItemizedOverlayImpl { - private CachesOverlay base; - private Lock lock = new ReentrantLock(); + private final CachesOverlay base; + private final Lock lock = new ReentrantLock(); - public MapsforgeCacheOverlay(Context contextIn, Drawable markerIn) { + public MapsforgeCacheOverlay(final Context contextIn, final Drawable markerIn) { super(boundCenterBottom(markerIn)); base = new CachesOverlay(this, contextIn); } @@ -32,7 +32,7 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay } @Override - protected MapsforgeCacheOverlayItem createItem(int i) { + protected MapsforgeCacheOverlayItem createItem(final int i) { if (base == null) { return null; } @@ -50,7 +50,7 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay } @Override - protected boolean onTap(int arg0) { + protected boolean onTap(final int arg0) { if (base == null) { return false; } @@ -59,8 +59,8 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay } @Override - protected void drawOverlayBitmap(Canvas canvas, Point drawPosition, - Projection projection, byte drawZoomLevel) { + protected void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final Projection projection, final byte drawZoomLevel) { base.drawOverlayBitmap(canvas, drawPosition, new MapsforgeMapProjection(projection), drawZoomLevel); } @@ -70,28 +70,28 @@ public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlay } @Override - public Drawable superBoundCenterBottom(Drawable marker) { + public Drawable superBoundCenterBottom(final Drawable marker) { return ItemizedOverlay.boundCenterBottom(marker); } @Override - public void superSetLastFocusedItemIndex(int i) { + public void superSetLastFocusedItemIndex(final int i) { // nothing to do } @Override - public boolean superOnTap(int index) { + public boolean superOnTap(final int index) { return super.onTap(index); } @Override - public void superDraw(Canvas canvas, MapViewImpl mapView, boolean shadow) { + public void superDraw(final Canvas canvas, final MapViewImpl mapView, final boolean shadow) { // nothing to do here... } @Override - public void superDrawOverlayBitmap(Canvas canvas, Point drawPosition, - MapProjectionImpl projection, byte drawZoomLevel) { + public void superDrawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final MapProjectionImpl projection, final byte drawZoomLevel) { super.drawOverlayBitmap(canvas, drawPosition, (Projection) projection.getImpl(), drawZoomLevel); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java index 27ca664..4a1b080 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeCacheOverlayItem.java @@ -12,7 +12,7 @@ public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOver final private IWaypoint coord; final private boolean applyDistanceRule; - public MapsforgeCacheOverlayItem(IWaypoint coordinate, boolean applyDistanceRule) { + public MapsforgeCacheOverlayItem(final IWaypoint coordinate, final boolean applyDistanceRule) { super(new GeoPoint(coordinate.getCoords().getLatitudeE6(), coordinate.getCoords().getLongitudeE6()), coordinate.getName(), ""); this.coord = coordinate; @@ -25,7 +25,7 @@ public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOver } @Override - public Drawable getMarker(int index) { + public Drawable getMarker(final int index) { return getMarker(); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java index 197bd76..25269e6 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeGeoPoint.java @@ -1,6 +1,6 @@ package cgeo.geocaching.maps.mapsforge; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import org.mapsforge.core.GeoPoint; @@ -9,7 +9,7 @@ public class MapsforgeGeoPoint extends GeoPoint implements GeoPointImpl { private static final long serialVersionUID = 1L; - public MapsforgeGeoPoint(int latitudeE6, int longitudeE6) { + public MapsforgeGeoPoint(final int latitudeE6, final int longitudeE6) { super(latitudeE6, longitudeE6); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java index 94213ba..5220e05 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java @@ -16,7 +16,7 @@ import android.view.View; public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl, FilteredActivity { - private AbstractMap mapBase; + private final AbstractMap mapBase; public MapsforgeMapActivity() { mapBase = new CGeoMap(this); @@ -28,7 +28,7 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl } @Override - protected void onCreate(Bundle icicle) { + protected void onCreate(final Bundle icicle) { mapBase.onCreate(icicle); } @@ -53,17 +53,17 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl } @Override - public boolean onCreateOptionsMenu(Menu menu) { + public boolean onCreateOptionsMenu(final Menu menu) { return mapBase.onCreateOptionsMenu(menu); } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { return mapBase.onOptionsItemSelected(item); } @Override - public boolean onPrepareOptionsMenu(Menu menu) { + public boolean onPrepareOptionsMenu(final Menu menu) { return mapBase.onPrepareOptionsMenu(menu); } @@ -73,12 +73,12 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl } @Override - public void superOnCreate(Bundle savedInstanceState) { + public void superOnCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override - public boolean superOnCreateOptionsMenu(Menu menu) { + public boolean superOnCreateOptionsMenu(final Menu menu) { return super.onCreateOptionsMenu(menu); } @@ -88,7 +88,7 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl } @Override - public boolean superOnOptionsItemSelected(MenuItem item) { + public boolean superOnOptionsItemSelected(final MenuItem item) { return super.onOptionsItemSelected(item); } @@ -108,17 +108,17 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl } @Override - public boolean superOnPrepareOptionsMenu(Menu menu) { + public boolean superOnPrepareOptionsMenu(final Menu menu) { return super.onPrepareOptionsMenu(menu); } @Override - public void navigateUp(View view) { + public void navigateUp(final View view) { ActivityMixin.navigateUp(this); } @Override - public void showFilterMenu(View view) { + public void showFilterMenu(final View view) { // do nothing, the filter bar only shows the global filter } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapController.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapController.java index 8b2e1e9..cfce07d 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapController.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapController.java @@ -8,26 +8,26 @@ import org.mapsforge.core.GeoPoint; public class MapsforgeMapController implements MapControllerImpl { - private MapController mapController; - private int maxZoomLevel; + private final MapController mapController; + private final int maxZoomLevel; - public MapsforgeMapController(MapController mapControllerIn, int maxZoomLevelIn) { + public MapsforgeMapController(final MapController mapControllerIn, final int maxZoomLevelIn) { mapController = mapControllerIn; maxZoomLevel = maxZoomLevelIn; } @Override - public void animateTo(GeoPointImpl geoPoint) { + public void animateTo(final GeoPointImpl geoPoint) { mapController.setCenter(castToGeoPoint(geoPoint)); } - private static GeoPoint castToGeoPoint(GeoPointImpl geoPoint) { + private static GeoPoint castToGeoPoint(final GeoPointImpl geoPoint) { assert geoPoint instanceof GeoPoint; return (GeoPoint) geoPoint; } @Override - public void setCenter(GeoPointImpl geoPoint) { + public void setCenter(final GeoPointImpl geoPoint) { mapController.setCenter(castToGeoPoint(geoPoint)); } @@ -36,19 +36,19 @@ public class MapsforgeMapController implements MapControllerImpl { * mapzoom-1 is used to be compatible with Google Maps zoom levels */ @Override - public void setZoom(int mapzoom) { + public void setZoom(final int mapzoom) { // Google Maps and OSM Maps use different zoom levels for the same view. // All OSM Maps zoom levels are offset by 1 so they match Google Maps. mapController.setZoom(Math.min(mapzoom - 1, maxZoomLevel)); } @Override - public void zoomToSpan(int latSpanE6, int lonSpanE6) { + public void zoomToSpan(final int latSpanE6, final int lonSpanE6) { if (latSpanE6 != 0 && lonSpanE6 != 0) { // calculate zoomlevel - int distDegree = Math.max(latSpanE6, lonSpanE6); - int zoomLevel = (int) Math.floor(Math.log(360.0 * 1e6 / distDegree) / Math.log(2)); + final int distDegree = Math.max(latSpanE6, lonSpanE6); + final int zoomLevel = (int) Math.floor(Math.log(360.0 * 1e6 / distDegree) / Math.log(2)); mapController.setZoom(zoomLevel + 1); } } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java index 4ade09c..8adf4ad 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapItemFactory.java @@ -1,7 +1,7 @@ package cgeo.geocaching.maps.mapsforge; import cgeo.geocaching.IWaypoint; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; import cgeo.geocaching.maps.interfaces.GeoPointImpl; import cgeo.geocaching.maps.interfaces.MapItemFactory; @@ -14,7 +14,7 @@ public class MapsforgeMapItemFactory implements MapItemFactory { } @Override - public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) { + public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, final boolean applyDistanceRule) { return new MapsforgeCacheOverlayItem(coordinate, applyDistanceRule); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProjection.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProjection.java index 68d7123..a042eca 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProjection.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProjection.java @@ -10,14 +10,14 @@ import android.graphics.Point; public class MapsforgeMapProjection implements MapProjectionImpl { - private Projection projection; + private final Projection projection; - public MapsforgeMapProjection(Projection projectionIn) { + public MapsforgeMapProjection(final Projection projectionIn) { projection = projectionIn; } @Override - public void toPixels(GeoPointImpl leftGeo, Point left) { + public void toPixels(final GeoPointImpl leftGeo, final Point left) { projection.toPixels((GeoPoint) leftGeo, left); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java index 01b10ec..76d645c 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java @@ -7,8 +7,6 @@ import cgeo.geocaching.maps.MapProviderFactory; import cgeo.geocaching.maps.interfaces.MapItemFactory; import cgeo.geocaching.maps.interfaces.MapProvider; import cgeo.geocaching.maps.interfaces.MapSource; -import cgeo.geocaching.maps.mapsforge.v024.MapsforgeMapActivity024; -import cgeo.geocaching.maps.mapsforge.v024.MapsforgeMapItemFactory024; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; @@ -30,7 +28,6 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { public static final String MAPSFORGE_CYCLEMAP_ID = "MAPSFORGE_CYCLEMAP"; public static final String MAPSFORGE_MAPNIK_ID = "MAPSFORGE_MAPNIK"; - private boolean oldMap = false; private MapItemFactory mapItemFactory = new MapsforgeMapItemFactory(); private MapsforgeMapProvider() { @@ -56,13 +53,13 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { return Collections.emptyList(); } - File directory = new File(directoryPath); + final File directory = new File(directoryPath); if (directory.isDirectory()) { try { - ArrayList<String> mapFileList = new ArrayList<>(); + final ArrayList<String> mapFileList = new ArrayList<>(); final File[] files = directory.listFiles(); if (ArrayUtils.isNotEmpty(files)) { - for (File file : files) { + for (final File file : files) { if (file.getName().endsWith(".map")) { if (MapsforgeMapProvider.isValidMapFile(file.getAbsolutePath())) { mapFileList.add(file.getAbsolutePath()); @@ -72,69 +69,44 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { Collections.sort(mapFileList, String.CASE_INSENSITIVE_ORDER); } return mapFileList; - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapProvider.getOfflineMaps: ", e); } } return Collections.emptyList(); } - public static boolean isValidMapFile(String mapFileIn) { + public static boolean isValidMapFile(final String mapFileIn) { if (StringUtils.isEmpty(mapFileIn)) { return false; } - MapDatabase mapDB = new MapDatabase(); - FileOpenResult result = mapDB.openFile(new File(mapFileIn)); + final MapDatabase mapDB = new MapDatabase(); + final FileOpenResult result = mapDB.openFile(new File(mapFileIn)); mapDB.closeFile(); - boolean isValid = result.isSuccess(); - - if (!isValid) { - isValid = isMapfile024(mapFileIn); - } - - return isValid; - } - - private static boolean isMapfile024(String mapFileIn) { - return mapFileIn != null && org.mapsforge.android.mapsold.MapDatabase.isValidMapFile(mapFileIn); + return result.isSuccess(); } @Override public boolean isSameActivity(final MapSource source1, final MapSource source2) { - return source1 == source2 || - !isMapfile024(Settings.getMapFile()) || - (!(source1 instanceof OfflineMapSource) && !(source2 instanceof OfflineMapSource)); + return source1.getNumericalId() == source2.getNumericalId() || (!(source1 instanceof OfflineMapSource) && !(source2 instanceof OfflineMapSource)); } @Override public Class<? extends Activity> getMapClass() { - final MapSource source = Settings.getMapSource(); - if (source instanceof OfflineMapSource && isMapfile024(Settings.getMapFile())) { - oldMap = true; - mapItemFactory = new MapsforgeMapItemFactory024(); - return MapsforgeMapActivity024.class; - } - oldMap = false; mapItemFactory = new MapsforgeMapItemFactory(); return MapsforgeMapActivity.class; } @Override public int getMapViewId() { - if (oldMap) { - return R.id.mfmap_old; - } return R.id.mfmap; } @Override public int getMapLayoutId() { - if (oldMap) { - return R.layout.map_mapsforge_old; - } return R.layout.map_mapsforge; } @@ -152,7 +124,7 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { private final String fileName; - public OfflineMapSource(final String fileName, MapProvider mapProvider, final String name, final MapGeneratorInternal generator) { + public OfflineMapSource(final String fileName, final MapProvider mapProvider, final String name, final MapGeneratorInternal generator) { super(fileName, mapProvider, name, generator); this.fileName = fileName; } @@ -171,7 +143,7 @@ public final class MapsforgeMapProvider extends AbstractMapProvider { MapProviderFactory.deleteOfflineMapSources(); final Resources resources = CgeoApplication.getInstance().getResources(); final List<String> offlineMaps = getOfflineMaps(); - for (String mapFile : offlineMaps) { + for (final String mapFile : offlineMaps) { final String mapName = StringUtils.capitalize(StringUtils.substringBeforeLast(new File(mapFile).getName(), ".")); registerMapSource(new OfflineMapSource(mapFile, this, mapName + " (" + resources.getString(R.string.map_source_osm_offline) + ")", MapGeneratorInternal.DATABASE_RENDERER)); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapSource.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapSource.java index 861e567..23e9a23 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapSource.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapSource.java @@ -9,7 +9,7 @@ class MapsforgeMapSource extends AbstractMapSource { private final MapGeneratorInternal generator; - public MapsforgeMapSource(final String id, MapProvider mapProvider, String name, MapGeneratorInternal generator) { + public MapsforgeMapSource(final String id, final MapProvider mapProvider, final String name, final MapGeneratorInternal generator) { super(id, mapProvider, name); this.generator = generator; } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java index d95cc80..71bf583 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java @@ -1,7 +1,8 @@ package cgeo.geocaching.maps.mapsforge; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.CachesOverlay; import cgeo.geocaching.maps.PositionAndScaleOverlay; import cgeo.geocaching.maps.interfaces.GeneralOverlay; @@ -40,12 +41,12 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { private OnMapDragListener onDragListener; private final MapsforgeMapController mapController = new MapsforgeMapController(getController(), getMapGenerator().getZoomLevelMax()); - public MapsforgeMapView(Context context, AttributeSet attrs) { + public MapsforgeMapView(final Context context, final AttributeSet attrs) { super(context, attrs); initialize(context); } - private void initialize(Context context) { + private void initialize(final Context context) { if (isInEditMode()) { return; } @@ -56,7 +57,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public void draw(@NonNull Canvas canvas) { + public void draw(@NonNull final Canvas canvas) { try { // Google Maps and OSM Maps use different zoom levels for the same view. // Here we don't want the Google Maps compatible zoom level, but the actual one. @@ -65,13 +66,13 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } super.draw(canvas); - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapView.draw", e); } } @Override - public void displayZoomControls(boolean takeFocus) { + public void displayZoomControls(final boolean takeFocus) { // nothing to do here } @@ -83,7 +84,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { @Override @NonNull public GeoPointImpl getMapViewCenter() { - GeoPoint point = getMapPosition().getMapCenter(); + final GeoPoint point = getMapPosition().getMapCenter(); return new MapsforgeGeoPoint(point.latitudeE6, point.longitudeE6); } @@ -103,16 +104,16 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public CachesOverlay createAddMapOverlay(Context context, Drawable drawable) { + public CachesOverlay createAddMapOverlay(final Context context, final Drawable drawable) { - MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); + final MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); getOverlays().add(ovl); return ovl.getBase(); } @Override - public PositionAndScaleOverlay createAddPositionAndScaleOverlay() { - MapsforgeOverlay ovl = new MapsforgeOverlay(); + public PositionAndScaleOverlay createAddPositionAndScaleOverlay(final Geopoint coords, final String geocode) { + final MapsforgeOverlay ovl = new MapsforgeOverlay(this, coords, geocode); getOverlays().add(ovl); return (PositionAndScaleOverlay) ovl.getBase(); } @@ -122,12 +123,12 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { int span = 0; - Projection projection = getProjection(); + final Projection projection = getProjection(); if (projection != null && getHeight() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(0, getHeight()); + final GeoPoint low = projection.fromPixels(0, 0); + final GeoPoint high = projection.fromPixels(0, getHeight()); if (low != null && high != null) { span = Math.abs(high.latitudeE6 - low.latitudeE6); @@ -142,11 +143,11 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { int span = 0; - Projection projection = getProjection(); + final Projection projection = getProjection(); if (projection != null && getWidth() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(getWidth(), 0); + final GeoPoint low = projection.fromPixels(0, 0); + final GeoPoint high = projection.fromPixels(getWidth(), 0); if (low != null && high != null) { span = Math.abs(high.longitudeE6 - low.longitudeE6); @@ -191,7 +192,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { newMapType = ((MapsforgeMapSource) mapSource).getGenerator(); } - MapGenerator mapGenerator = MapGeneratorFactory.createMapGenerator(newMapType); + final MapGenerator mapGenerator = MapGeneratorFactory.createMapGenerator(newMapType); // When swapping map sources, make sure we aren't exceeding max zoom. See bug #1535 final int maxZoom = mapGenerator.getZoomLevelMax(); @@ -230,11 +231,11 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { @Override public void setMapTheme() { - String customRenderTheme = Settings.getCustomRenderThemeFilePath(); + final String customRenderTheme = Settings.getCustomRenderThemeFilePath(); if (StringUtils.isNotEmpty(customRenderTheme)) { try { setRenderTheme(new File(customRenderTheme)); - } catch (FileNotFoundException e) { + } catch (final FileNotFoundException ignored) { Toast.makeText( getContext(), getContext().getResources().getString(R.string.warn_rendertheme_missing), @@ -247,38 +248,38 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public void repaintRequired(GeneralOverlay overlay) { + public void repaintRequired(final GeneralOverlay overlay) { if (null == overlay) { invalidate(); } else { try { - Overlay ovl = (Overlay) overlay.getOverlayImpl(); + final Overlay ovl = (Overlay) overlay.getOverlayImpl(); if (ovl != null) { ovl.requestRedraw(); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("MapsforgeMapView.repaintRequired", e); } } } @Override - public void setOnDragListener(OnMapDragListener onDragListener) { + public void setOnDragListener(final OnMapDragListener onDragListener) { this.onDragListener = onDragListener; } @Override - public boolean onTouchEvent(MotionEvent ev) { + public boolean onTouchEvent(final MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.onTouchEvent(ev); } private class GestureListener extends SimpleOnGestureListener { @Override - public boolean onDoubleTap(MotionEvent e) { + public boolean onDoubleTap(final MotionEvent e) { if (onDragListener != null) { onDragListener.onDrag(); } @@ -286,8 +287,8 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { } @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { + public boolean onScroll(final MotionEvent e1, final MotionEvent e2, + final float distanceX, final float distanceY) { if (onDragListener != null) { onDragListener.onDrag(); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java index 3df4ab0..3926eb6 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.maps.PositionAndScaleOverlay; import cgeo.geocaching.maps.interfaces.GeneralOverlay; import cgeo.geocaching.maps.interfaces.MapViewImpl; @@ -17,15 +18,15 @@ import java.util.concurrent.locks.ReentrantLock; public class MapsforgeOverlay extends Overlay implements OverlayImpl { private PositionAndScaleOverlay overlayBase = null; - private Lock lock = new ReentrantLock(); + private final Lock lock = new ReentrantLock(); - public MapsforgeOverlay() { - overlayBase = new PositionAndScaleOverlay(this); + public MapsforgeOverlay(final MapViewImpl mapView, final Geopoint coords, final String geocode) { + overlayBase = new PositionAndScaleOverlay(this, mapView, coords, geocode); } @Override - protected void drawOverlayBitmap(Canvas canvas, Point drawPosition, - Projection projection, byte drawZoomLevel) { + protected void drawOverlayBitmap(final Canvas canvas, final Point drawPosition, + final Projection projection, final byte drawZoomLevel) { if (overlayBase != null) { overlayBase.drawOverlayBitmap(canvas, drawPosition, new MapsforgeMapProjection(projection), drawZoomLevel); diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java deleted file mode 100644 index a8111ed..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlay.java +++ /dev/null @@ -1,113 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.maps.CachesOverlay; -import cgeo.geocaching.maps.interfaces.ItemizedOverlayImpl; -import cgeo.geocaching.maps.interfaces.MapProjectionImpl; -import cgeo.geocaching.maps.interfaces.MapViewImpl; - -import org.mapsforge.android.mapsold.ItemizedOverlay; -import org.mapsforge.android.mapsold.Projection; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Point; -import android.graphics.drawable.Drawable; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -public class MapsforgeCacheOverlay extends ItemizedOverlay<MapsforgeCacheOverlayItem> implements ItemizedOverlayImpl { - - private CachesOverlay base; - private Lock lock = new ReentrantLock(); - - public MapsforgeCacheOverlay(Context contextIn, Drawable markerIn) { - super(boundCenterBottom(markerIn)); - base = new CachesOverlay(this, contextIn); - } - - @Override - public CachesOverlay getBase() { - return base; - } - - @Override - protected MapsforgeCacheOverlayItem createItem(int i) { - if (base == null) { - return null; - } - - return (MapsforgeCacheOverlayItem) base.createItem(i); - } - - @Override - public int size() { - if (base == null) { - return 0; - } - - return base.size(); - } - - @Override - protected boolean onTap(int arg0) { - if (base == null) { - return false; - } - - return base.onTap(arg0); - } - - @Override - protected void drawOverlayBitmap(Canvas canvas, Point drawPosition, - Projection projection, byte drawZoomLevel) { - base.drawOverlayBitmap(canvas, drawPosition, new MapsforgeMapProjection(projection), drawZoomLevel); - } - - @Override - public void superPopulate() { - populate(); - } - - @Override - public Drawable superBoundCenterBottom(Drawable marker) { - return ItemizedOverlay.boundCenterBottom(marker); - } - - @Override - public void superSetLastFocusedItemIndex(int i) { - // nothing to do - } - - @Override - public boolean superOnTap(int index) { - return super.onTap(index); - } - - @Override - public void superDraw(Canvas canvas, MapViewImpl mapView, boolean shadow) { - // nothing to do here... - } - - @Override - public void superDrawOverlayBitmap(Canvas canvas, Point drawPosition, - MapProjectionImpl projection, byte drawZoomLevel) { - super.drawOverlayBitmap(canvas, drawPosition, (Projection) projection.getImpl(), drawZoomLevel); - } - - @Override - public void lock() { - lock.lock(); - } - - @Override - public void unlock() { - lock.unlock(); - } - - @Override - public MapViewImpl getMapViewImpl() { - return (MapViewImpl) internalMapView; - } - -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java deleted file mode 100644 index 4e4a358..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeCacheOverlayItem.java +++ /dev/null @@ -1,37 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.IWaypoint; -import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; - -import org.mapsforge.android.mapsold.GeoPoint; -import org.mapsforge.android.mapsold.OverlayItem; - -import android.graphics.drawable.Drawable; - -public class MapsforgeCacheOverlayItem extends OverlayItem implements CachesOverlayItemImpl { - final private IWaypoint coord; - final private boolean applyDistanceRule; - - public MapsforgeCacheOverlayItem(IWaypoint coordinate, boolean applyDistanceRule) { - super(new GeoPoint(coordinate.getCoords().getLatitudeE6(), coordinate.getCoords().getLongitudeE6()), coordinate.getName(), ""); - - this.coord = coordinate; - this.applyDistanceRule = applyDistanceRule; - } - - @Override - public IWaypoint getCoord() { - return coord; - } - - @Override - public Drawable getMarker(int index) { - return getMarker(); - } - - @Override - public boolean applyDistanceRule() { - return applyDistanceRule; - } - -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeGeoPoint.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeGeoPoint.java deleted file mode 100644 index c801e3f..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeGeoPoint.java +++ /dev/null @@ -1,18 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.maps.interfaces.GeoPointImpl; - -import org.mapsforge.android.mapsold.GeoPoint; - -public class MapsforgeGeoPoint extends GeoPoint implements GeoPointImpl { - - public MapsforgeGeoPoint(int latitudeE6, int longitudeE6) { - super(latitudeE6, longitudeE6); - } - - @Override - public Geopoint getCoords() { - return new Geopoint(getLatitudeE6() / 1e6, getLongitudeE6() / 1e6); - } -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java deleted file mode 100644 index daeb2b8..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java +++ /dev/null @@ -1,124 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.activity.FilteredActivity; -import cgeo.geocaching.maps.AbstractMap; -import cgeo.geocaching.maps.CGeoMap; -import cgeo.geocaching.maps.interfaces.MapActivityImpl; - -import org.mapsforge.android.mapsold.MapActivity; - -import android.app.Activity; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; - -public class MapsforgeMapActivity024 extends MapActivity implements MapActivityImpl, FilteredActivity { - - private AbstractMap mapBase; - - public MapsforgeMapActivity024() { - mapBase = new CGeoMap(this); - } - - @Override - public Activity getActivity() { - return this; - } - - @Override - protected void onCreate(Bundle icicle) { - mapBase.onCreate(icicle); - } - - @Override - protected void onSaveInstanceState(final Bundle outState) { - mapBase.onSaveInstanceState(outState); - } - - @Override - protected void onDestroy() { - mapBase.onDestroy(); - } - - @Override - protected void onPause() { - mapBase.onPause(); - } - - @Override - protected void onResume() { - mapBase.onResume(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - return mapBase.onCreateOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return mapBase.onOptionsItemSelected(item); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - return mapBase.onPrepareOptionsMenu(menu); - } - - @Override - protected void onStop() { - mapBase.onStop(); - } - - @Override - public void superOnCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public boolean superOnCreateOptionsMenu(Menu menu) { - return super.onCreateOptionsMenu(menu); - } - - @Override - public void superOnDestroy() { - super.onDestroy(); - } - - @Override - public boolean superOnOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); - } - - @Override - public void superOnResume() { - super.onResume(); - } - - @Override - public void superOnStop() { - super.onStop(); - } - - @Override - public void superOnPause() { - super.onPause(); - } - - @Override - public boolean superOnPrepareOptionsMenu(Menu menu) { - return super.onPrepareOptionsMenu(menu); - } - - @Override - public void navigateUp(View view) { - ActivityMixin.navigateUp(this); - } - - @Override - public void showFilterMenu(View view) { - // do nothing, the filter bar only shows the global filter - } -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapController.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapController.java deleted file mode 100644 index db33d56..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapController.java +++ /dev/null @@ -1,55 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.maps.interfaces.GeoPointImpl; -import cgeo.geocaching.maps.interfaces.MapControllerImpl; - -import org.mapsforge.android.mapsold.GeoPoint; -import org.mapsforge.android.mapsold.MapController; - -public class MapsforgeMapController implements MapControllerImpl { - - private MapController mapController; - private int maxZoomLevel; - - public MapsforgeMapController(MapController mapControllerIn, int maxZoomLevelIn) { - mapController = mapControllerIn; - maxZoomLevel = maxZoomLevelIn; - } - - @Override - public void animateTo(GeoPointImpl geoPoint) { - mapController.setCenter(castToGeoPointImpl(geoPoint)); - } - - private static GeoPoint castToGeoPointImpl(GeoPointImpl geoPoint) { - assert geoPoint instanceof GeoPoint; - return (GeoPoint) geoPoint; - } - - @Override - public void setCenter(GeoPointImpl geoPoint) { - mapController.setCenter(castToGeoPointImpl(geoPoint)); - } - - /** - * Set the map zoom level to mapzoom-1 or maxZoomLevel, whichever is least - * mapzoom-1 is used to be compatible with Google Maps zoom levels - */ - @Override - public void setZoom(int mapzoom) { - // Google Maps and OSM Maps use different zoom levels for the same view. - // All OSM Maps zoom levels are offset by 1 so they match Google Maps. - mapController.setZoom(Math.min(mapzoom - 1, maxZoomLevel)); - } - - @Override - public void zoomToSpan(int latSpanE6, int lonSpanE6) { - - if (latSpanE6 != 0 && lonSpanE6 != 0) { - // calculate zoomlevel - int distDegree = Math.max(latSpanE6, lonSpanE6); - int zoomLevel = (int) Math.floor(Math.log(360.0 * 1e6 / distDegree) / Math.log(2)); - mapController.setZoom(zoomLevel + 1); - } - } -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java deleted file mode 100644 index 4f1d34c..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapItemFactory024.java +++ /dev/null @@ -1,20 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.IWaypoint; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; -import cgeo.geocaching.maps.interfaces.GeoPointImpl; -import cgeo.geocaching.maps.interfaces.MapItemFactory; - -public class MapsforgeMapItemFactory024 implements MapItemFactory { - - @Override - public GeoPointImpl getGeoPointBase(final Geopoint coords) { - return new MapsforgeGeoPoint(coords.getLatitudeE6(), coords.getLongitudeE6()); - } - - @Override - public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) { - return new MapsforgeCacheOverlayItem(coordinate, applyDistanceRule); - } -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapProjection.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapProjection.java deleted file mode 100644 index 9d36b7d..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapProjection.java +++ /dev/null @@ -1,29 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.maps.interfaces.GeoPointImpl; -import cgeo.geocaching.maps.interfaces.MapProjectionImpl; - -import org.mapsforge.android.mapsold.GeoPoint; -import org.mapsforge.android.mapsold.Projection; - -import android.graphics.Point; - -public class MapsforgeMapProjection implements MapProjectionImpl { - - private Projection projection; - - public MapsforgeMapProjection(Projection projectionIn) { - projection = projectionIn; - } - - @Override - public void toPixels(GeoPointImpl leftGeo, Point left) { - projection.toPixels((GeoPoint) leftGeo, left); - } - - @Override - public Object getImpl() { - return projection; - } - -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java deleted file mode 100644 index 8dd15fc..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java +++ /dev/null @@ -1,254 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Viewport; -import cgeo.geocaching.maps.CachesOverlay; -import cgeo.geocaching.maps.PositionAndScaleOverlay; -import cgeo.geocaching.maps.interfaces.GeneralOverlay; -import cgeo.geocaching.maps.interfaces.GeoPointImpl; -import cgeo.geocaching.maps.interfaces.MapControllerImpl; -import cgeo.geocaching.maps.interfaces.MapProjectionImpl; -import cgeo.geocaching.maps.interfaces.MapViewImpl; -import cgeo.geocaching.maps.interfaces.OnMapDragListener; -import cgeo.geocaching.settings.Settings; -import cgeo.geocaching.utils.Log; - -import org.eclipse.jdt.annotation.NonNull; -import org.mapsforge.android.mapsold.GeoPoint; -import org.mapsforge.android.mapsold.MapDatabase; -import org.mapsforge.android.mapsold.MapView; -import org.mapsforge.android.mapsold.MapViewMode; -import org.mapsforge.android.mapsold.Overlay; -import org.mapsforge.android.mapsold.Projection; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.GestureDetector.SimpleOnGestureListener; -import android.view.MotionEvent; -import android.widget.Toast; -public class MapsforgeMapView024 extends MapView implements MapViewImpl { - private GestureDetector gestureDetector; - private OnMapDragListener onDragListener; - private final MapsforgeMapController mapController = new MapsforgeMapController(getController(), getMaxZoomLevel()); - - public MapsforgeMapView024(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(context); - } - - private void initialize(Context context) { - if (isInEditMode()) { - return; - } - gestureDetector = new GestureDetector(context, new GestureListener()); - } - - @Override - public void draw(@NonNull Canvas canvas) { - try { - // Google Maps and OSM Maps use different zoom levels for the same view. - // Here we don't want the Google Maps compatible zoom level, but the actual one. - if (getActualMapZoomLevel() > 22) { // to avoid too close zoom level (mostly on Samsung Galaxy S series) - getController().setZoom(22); - } - - super.draw(canvas); - } catch (Exception e) { - Log.e("MapsforgeMapView024.draw", e); - } - } - - @Override - public void displayZoomControls(boolean takeFocus) { - // nothing to do here - } - - @Override - public MapControllerImpl getMapController() { - return mapController; - } - - @Override - @NonNull - public GeoPointImpl getMapViewCenter() { - GeoPoint point = getMapCenter(); - return new MapsforgeGeoPoint(point.getLatitudeE6(), point.getLongitudeE6()); - } - - @Override - public Viewport getViewport() { - return new Viewport(getMapViewCenter(), getLatitudeSpan() / 1e6, getLongitudeSpan() / 1e6); - } - - @Override - public void clearOverlays() { - getOverlays().clear(); - } - - @Override - public MapProjectionImpl getMapProjection() { - return new MapsforgeMapProjection(getProjection()); - } - - @Override - public CachesOverlay createAddMapOverlay(Context context, Drawable drawable) { - - MapsforgeCacheOverlay ovl = new MapsforgeCacheOverlay(context, drawable); - getOverlays().add(ovl); - return ovl.getBase(); - } - - @Override - public PositionAndScaleOverlay createAddPositionAndScaleOverlay() { - MapsforgeOverlay ovl = new MapsforgeOverlay(); - getOverlays().add(ovl); - return (PositionAndScaleOverlay) ovl.getBase(); - } - - @Override - public int getLatitudeSpan() { - - int span = 0; - - Projection projection = getProjection(); - - if (projection != null && getHeight() > 0) { - - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(0, getHeight()); - - if (low != null && high != null) { - span = Math.abs(high.getLatitudeE6() - low.getLatitudeE6()); - } - } - - return span; - } - - @Override - public int getLongitudeSpan() { - - int span = 0; - - Projection projection = getProjection(); - - if (projection != null && getWidth() > 0) { - GeoPoint low = projection.fromPixels(0, 0); - GeoPoint high = projection.fromPixels(getWidth(), 0); - - if (low != null && high != null) { - span = Math.abs(high.getLongitudeE6() - low.getLongitudeE6()); - } - } - - return span; - } - - @Override - public void preLoad() { - // Nothing to do here - } - - /** - * Get the map zoom level which is compatible with Google Maps. - * - * @return the current map zoom level +1 - */ - @Override - public int getMapZoomLevel() { - // Google Maps and OSM Maps use different zoom levels for the same view. - // All OSM Maps zoom levels are offset by 1 so they match Google Maps. - return getZoomLevel() + 1; - } - - /** - * Get the actual map zoom level - * - * @return the current map zoom level with no adjustments - */ - private int getActualMapZoomLevel() { - return getZoomLevel(); - } - - @Override - public void setMapSource() { - setMapViewMode(MapViewMode.CANVAS_RENDERER); - setMapFile(Settings.getMapFile()); - if (!MapDatabase.isValidMapFile(Settings.getMapFile())) { - Log.e("MapsforgeMapView024: Invalid map file"); - } - Toast.makeText( - getContext(), - getContext().getResources().getString(R.string.warn_deprecated_mapfile), - Toast.LENGTH_LONG) - .show(); - } - - @Override - public void repaintRequired(GeneralOverlay overlay) { - - if (null == overlay) { - invalidate(); - } else { - try { - Overlay ovl = (Overlay) overlay.getOverlayImpl(); - - if (ovl != null) { - ovl.requestRedraw(); - } - - } catch (Exception e) { - Log.e("MapsforgeMapView024.repaintRequired", e); - } - } - } - - @Override - public void setOnDragListener(OnMapDragListener onDragListener) { - this.onDragListener = onDragListener; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - gestureDetector.onTouchEvent(ev); - return super.onTouchEvent(ev); - } - - private class GestureListener extends SimpleOnGestureListener { - @Override - public boolean onDoubleTap(MotionEvent e) { - if (onDragListener != null) { - onDragListener.onDrag(); - } - return true; - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { - if (onDragListener != null) { - onDragListener.onDrag(); - } - return super.onScroll(e1, e2, distanceX, distanceY); - } - } - - @Override - public boolean needsInvertedColors() { - return false; - } - - @Override - public boolean hasMapThemes() { - // not supported - return false; - } - - @Override - public void setMapTheme() { - // not supported - } -} diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java deleted file mode 100644 index bfb3548..0000000 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeOverlay.java +++ /dev/null @@ -1,54 +0,0 @@ -package cgeo.geocaching.maps.mapsforge.v024; - -import cgeo.geocaching.maps.PositionAndScaleOverlay; -import cgeo.geocaching.maps.interfaces.GeneralOverlay; -import cgeo.geocaching.maps.interfaces.MapViewImpl; -import cgeo.geocaching.maps.interfaces.OverlayImpl; - -import org.mapsforge.android.mapsold.Overlay; -import org.mapsforge.android.mapsold.Projection; - -import android.graphics.Canvas; -import android.graphics.Point; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -public class MapsforgeOverlay extends Overlay implements OverlayImpl { - - private PositionAndScaleOverlay overlayBase = null; - private Lock lock = new ReentrantLock(); - - public MapsforgeOverlay() { - overlayBase = new PositionAndScaleOverlay(this); - } - - @Override - protected void drawOverlayBitmap(Canvas canvas, Point drawPosition, - Projection projection, byte drawZoomLevel) { - - if (overlayBase != null) { - overlayBase.drawOverlayBitmap(canvas, drawPosition, new MapsforgeMapProjection(projection), drawZoomLevel); - } - } - - public GeneralOverlay getBase() { - return overlayBase; - } - - @Override - public void lock() { - lock.lock(); - } - - @Override - public void unlock() { - lock.unlock(); - } - - @Override - public MapViewImpl getMapViewImpl() { - return (MapViewImpl) internalMapView; - } - -} diff --git a/main/src/cgeo/geocaching/network/AndroidBeam.java b/main/src/cgeo/geocaching/network/AndroidBeam.java new file mode 100644 index 0000000..68b8f94 --- /dev/null +++ b/main/src/cgeo/geocaching/network/AndroidBeam.java @@ -0,0 +1,93 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.CgeoApplication; + +import org.apache.commons.io.Charsets; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.Nullable; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.nfc.NdefMessage; +import android.nfc.NdefRecord; +import android.nfc.NfcAdapter; +import android.nfc.NfcAdapter.CreateNdefMessageCallback; +import android.nfc.NfcEvent; +import android.os.Build; + +/** + * utility class managing all NFC related tasks + */ +public class AndroidBeam { + + private AndroidBeam() { + // utility class + } + + /** + * returns the URI transmitted via Android Beam, or the URI contained in the data of the intent + */ + @Nullable + public static Uri getUri(final Intent intent) { + if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { + final NdefMessage msg = (NdefMessage) intent.getExtras().getParcelableArray(NfcAdapter.EXTRA_NDEF_MESSAGES)[0]; + return Uri.parse("http://" + new String(msg.getRecords()[0].getPayload(), Charsets.UTF_8)); + } + return intent.getData(); + } + + // Do not support older devices than Android 4.0 + // Although there even are 2.3 devices (Nexus S) + // these are so few that we don't want to deal with the older (non Android Beam) API + + public interface ActivitySharingInterface { + /** Return an URL that represent the current activity for sharing or null for no sharing. */ + @Nullable + public String getAndroidBeamUri(); + } + + public static void enable(final Activity activity, final ActivitySharingInterface sharingInterface) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + initializeICSAndroidBeam(activity, createMessageCallback(sharingInterface)); + } + } + + public static void disable(final Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + initializeICSAndroidBeam(activity, null); + } + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private static void initializeICSAndroidBeam(final Activity activity, final CreateNdefMessageCallback messageCallback) { + final NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(activity); + if (nfcAdapter == null) { + return; + } + nfcAdapter.setNdefPushMessageCallback(messageCallback, activity); + + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private static CreateNdefMessageCallback createMessageCallback(final ActivitySharingInterface sharingInterface) { + return new NfcAdapter.CreateNdefMessageCallback() { + @Override + public NdefMessage createNdefMessage(final NfcEvent event) { + String uri = sharingInterface.getAndroidBeamUri(); + if (uri == null) { + return null; + } + // normalize our modified URLs for beaming + uri = StringUtils.replace(uri, "geocaching.com//", "geocaching.com/"); + final NdefRecord[] records = { + NdefRecord.createUri(uri), + NdefRecord.createApplicationRecord(CgeoApplication.getInstance().getPackageName()) + }; + return new NdefMessage(records); + } + }; + } + +} diff --git a/main/src/cgeo/geocaching/network/Cookies.java b/main/src/cgeo/geocaching/network/Cookies.java index bcfc893..27013ba 100644 --- a/main/src/cgeo/geocaching/network/Cookies.java +++ b/main/src/cgeo/geocaching/network/Cookies.java @@ -29,7 +29,7 @@ public abstract class Cookies { } public static String dumpCookieStore() { - StringBuilder cookies = new StringBuilder(); + final StringBuilder cookies = new StringBuilder(); for (final Cookie cookie : cookieStore.getCookies()) { cookies.append(cookie.getName()); cookies.append('='); diff --git a/main/src/cgeo/geocaching/network/DownloadProgress.java b/main/src/cgeo/geocaching/network/DownloadProgress.java new file mode 100644 index 0000000..e0f20dc --- /dev/null +++ b/main/src/cgeo/geocaching/network/DownloadProgress.java @@ -0,0 +1,15 @@ +package cgeo.geocaching.network; + +public class DownloadProgress { + + private DownloadProgress() { + // Do not instantiate + } + + public static final int MSG_DONE = -1; + public static final int MSG_SERVER_FAIL = -2; + public static final int MSG_NO_REGISTRATION = -3; + public static final int MSG_WAITING = 0; + public static final int MSG_LOADING = 1; + public static final int MSG_LOADED = 2; +} diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index 31edc9f..fe67af4 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -12,13 +12,13 @@ import cgeo.geocaching.utils.ImageUtils; import cgeo.geocaching.utils.ImageUtils.ContainerDrawable; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.RxUtils; +import cgeo.geocaching.utils.RxUtils.ObservableCache; import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -44,22 +44,14 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.util.Date; +import java.util.HashMap; +import java.util.Map; -public class HtmlImage implements Html.ImageGetter { +/** + * All-purpose image getter that can also be used as a ImageGetter interface when displaying caches. + */ - // This class implements an all-purpose image getter that can also be used as a ImageGetter interface - // when displaying caches. An instance mainly has three possible use cases: - // - If onlySave is true, getDrawable() will return null immediately and will queue the image retrieval - // and saving in the loading subject. Downloads will start in parallel when the blocking - // waitForBackgroundLoading() method is called, and they can be cancelled through the given handler. - // - If onlySave is false and the instance is called through fetchDrawable(), then an observable for the - // given URL will be returned. This observable will emit the local copy of the image if it is present, - // regardless of its freshness, then if needed an updated fresher copy after retrieving it from the network. - // - If onlySave is false and the instance is used as an ImageGetter, only the final version of the - // image will be returned, unless a view has been provided. If it has, then a dummy drawable is returned - // and is updated when the image is available, possibly several times if we had a stale copy of the image - // and then got a new one from the network. +public class HtmlImage implements Html.ImageGetter { private static final String[] BLOCKED = new String[] { "gccounter.de", @@ -79,9 +71,9 @@ public class HtmlImage implements Html.ImageGetter { }; public static final String SHARED = "shared"; - final private String geocode; + @NonNull final private String geocode; /** - * on error: return large error image, if <code>true</code>, otherwise empty 1x1 image + * on error: return large error image, if {@code true}, otherwise empty 1x1 image */ final private boolean returnErrorImage; final private int listId; @@ -89,25 +81,57 @@ public class HtmlImage implements Html.ImageGetter { final private int maxWidth; final private int maxHeight; final private Resources resources; - final private TextView view; + protected final TextView view; + final private Map<String, BitmapDrawable> cache = new HashMap<>(); + + final private ObservableCache<String, BitmapDrawable> observableCache = new ObservableCache<>(new Func1<String, Observable<BitmapDrawable>>() { + @Override + public Observable<BitmapDrawable> call(final String url) { + return fetchDrawableUncached(url); + } + }); // Background loading final private PublishSubject<Observable<String>> loading = PublishSubject.create(); - final private Observable<String> waitForEnd = Observable.merge(loading).publish().refCount(); - final CompositeSubscription subscription = new CompositeSubscription(waitForEnd.subscribe()); + final private Observable<String> waitForEnd = Observable.merge(loading).cache(); + final private CompositeSubscription subscription = new CompositeSubscription(waitForEnd.subscribe()); /** - * Create a new HtmlImage object with different behaviours depending on <tt>onlySave</tt> and <tt>view</tt> values. + * Create a new HtmlImage object with different behaviors depending on <tt>onlySave</tt> and <tt>view</tt> values. + * There are the three possible use cases: + * <ul> + * <li>If onlySave is true, {@link #getDrawable(String)} will return <tt>null</tt> immediately and will queue the + * image retrieval and saving in the loading subject. Downloads will start in parallel when the blocking + * {@link #waitForEndObservable(cgeo.geocaching.utils.CancellableHandler)} method is called, and they can be + * cancelled through the given handler.</li> + * <li>If <tt>onlySave</tt> is <tt>false</tt> and the instance is called through {@link #fetchDrawable(String)}, + * then an observable for the given URL will be returned. This observable will emit the local copy of the image if + * it is present regardless of its freshness, then if needed an updated fresher copy after retrieving it from the + * network.</li> + * <li>If <tt>onlySave</tt> is <tt>false</tt> and the instance is used as an {@link android.text.Html.ImageGetter}, + * only the final version of the image will be returned, unless a view has been provided. If it has, then a dummy + * drawable is returned and is updated when the image is available, possibly several times if we had a stale copy of + * the image and then got a new one from the network.</li> + * </ul> * - * @param geocode the geocode of the item for which we are requesting the image - * @param returnErrorImage set to <tt>true</tt> if an error image should be returned in case of a problem, - * <tt>false</tt> to get a transparent 1x1 image instead - * @param listId the list this cache belongs to, used to determine if an older image for the offline case can be used or not - * @param onlySave if set to <tt>true</tt>, {@link #getDrawable(String)} will only fetch and store the image, not return it - * @param view if non-null, {@link #getDrawable(String)} will return an initially empty drawable which will be redrawn when - * the image is ready through an invalidation of the given view + * @param geocode + * the geocode of the item for which we are requesting the image, or {@link #SHARED} to use the shared + * cache directory + * @param returnErrorImage + * set to <tt>true</tt> if an error image should be returned in case of a problem, <tt>false</tt> to get + * a transparent 1x1 image instead + * @param listId + * the list this cache belongs to, used to determine if an older image for the offline case can be used + * or not + * @param onlySave + * if set to <tt>true</tt>, {@link #getDrawable(String)} will only fetch and store the image, not return + * it + * @param view + * if non-null, {@link #getDrawable(String)} will return an initially empty drawable which will be + * redrawn when + * the image is ready through an invalidation of the given view */ - public HtmlImage(final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave, final TextView view) { + public HtmlImage(@NonNull final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave, final TextView view) { this.geocode = geocode; this.returnErrorImage = returnErrorImage; this.listId = listId; @@ -121,12 +145,12 @@ public class HtmlImage implements Html.ImageGetter { } /** - * Create a new HtmlImage object with different behaviours depending on <tt>onlySave</tt> value. No view object + * Create a new HtmlImage object with different behaviors depending on <tt>onlySave</tt> value. No view object * will be tied to this HtmlImage. * * For documentation, see {@link #HtmlImage(String, boolean, int, boolean, TextView)}. */ - public HtmlImage(final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave) { + public HtmlImage(@NonNull final String geocode, final boolean returnErrorImage, final int listId, final boolean onlySave) { this(geocode, returnErrorImage, listId, onlySave, null); } @@ -141,6 +165,9 @@ public class HtmlImage implements Html.ImageGetter { @Nullable @Override public BitmapDrawable getDrawable(final String url) { + if (cache.containsKey(url)) { + return cache.get(url); + } final Observable<BitmapDrawable> drawable = fetchDrawable(url); if (onlySave) { loading.onNext(drawable.map(new Func1<BitmapDrawable, String>() { @@ -149,30 +176,37 @@ public class HtmlImage implements Html.ImageGetter { return url; } })); + cache.put(url, null); return null; } - if (view == null) { - return drawable.toBlocking().lastOrDefault(null); - } + final BitmapDrawable result = view == null ? drawable.toBlocking().lastOrDefault(null) : getContainerDrawable(drawable); + cache.put(url, result); + return result; + } + + protected BitmapDrawable getContainerDrawable(final Observable<BitmapDrawable> drawable) { return new ContainerDrawable(view, drawable); } - // Caches are loaded from disk on a computation scheduler to avoid using more threads than cores while decoding - // the image. Downloads happen on downloadScheduler, in parallel with image decoding. public Observable<BitmapDrawable> fetchDrawable(final String url) { + return observableCache.get(url); + } + // Caches are loaded from disk on a computation scheduler to avoid using more threads than cores while decoding + // the image. Downloads happen on downloadScheduler, in parallel with image decoding. + private Observable<BitmapDrawable> fetchDrawableUncached(final String url) { if (StringUtils.isBlank(url) || ImageUtils.containsPattern(url, BLOCKED)) { - return Observable.from(ImageUtils.getTransparent1x1Drawable(resources)); + return Observable.just(ImageUtils.getTransparent1x1Drawable(resources)); } // Explicit local file URLs are loaded from the filesystem regardless of their age. The IO part is short // enough to make the whole operation on the computation scheduler. if (FileUtils.isFileUrl(url)) { - return Observable.defer(new Func0<Observable<? extends BitmapDrawable>>() { + return Observable.defer(new Func0<Observable<BitmapDrawable>>() { @Override - public Observable<? extends BitmapDrawable> call() { - final Bitmap bitmap = loadCachedImage(FileUtils.urlToFile(url), true).getLeft(); - return bitmap != null ? Observable.from(ImageUtils.scaleBitmapToFitDisplay(bitmap)) : Observable.<BitmapDrawable>empty(); + public Observable<BitmapDrawable> call() { + final Bitmap bitmap = loadCachedImage(FileUtils.urlToFile(url), true).left; + return bitmap != null ? Observable.just(ImageUtils.scaleBitmapToFitDisplay(bitmap)) : Observable.<BitmapDrawable>empty(); } }).subscribeOn(RxUtils.computationScheduler); } @@ -187,9 +221,9 @@ public class HtmlImage implements Html.ImageGetter { subscriber.add(RxUtils.computationScheduler.createWorker().schedule(new Action0() { @Override public void call() { - final Pair<BitmapDrawable, Boolean> loaded = loadFromDisk(); - final BitmapDrawable bitmap = loaded.getLeft(); - if (loaded.getRight()) { + final ImmutablePair<BitmapDrawable, Boolean> loaded = loadFromDisk(); + final BitmapDrawable bitmap = loaded.left; + if (loaded.right) { subscriber.onNext(bitmap); subscriber.onCompleted(); return; @@ -206,14 +240,9 @@ public class HtmlImage implements Html.ImageGetter { })); } - private Pair<BitmapDrawable, Boolean> loadFromDisk() { - final Pair<Bitmap, Boolean> loadResult = loadImageFromStorage(url, pseudoGeocode, shared); - final Bitmap bitmap = loadResult.getLeft(); - return new ImmutablePair<>(bitmap != null ? - ImageUtils.scaleBitmapToFitDisplay(bitmap) : - null, - loadResult.getRight() - ); + private ImmutablePair<BitmapDrawable, Boolean> loadFromDisk() { + final ImmutablePair<Bitmap, Boolean> loadResult = loadImageFromStorage(url, pseudoGeocode, shared); + return scaleImage(loadResult); } private void downloadAndSave(final Subscriber<? super BitmapDrawable> subscriber) { @@ -233,27 +262,33 @@ public class HtmlImage implements Html.ImageGetter { } if (onlySave) { subscriber.onCompleted(); - } else { - RxUtils.computationScheduler.createWorker().schedule(new Action0() { - @Override - public void call() { - final Pair<BitmapDrawable, Boolean> loaded = loadFromDisk(); - final BitmapDrawable image = loaded.getLeft(); - if (image != null) { - subscriber.onNext(image); - } else { - subscriber.onNext(returnErrorImage ? - new BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.image_not_loaded)) : - ImageUtils.getTransparent1x1Drawable(resources)); - } - subscriber.onCompleted(); - } - }); + return; } + RxUtils.computationScheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final ImmutablePair<BitmapDrawable, Boolean> loaded = loadFromDisk(); + final BitmapDrawable image = loaded.left; + if (image != null) { + subscriber.onNext(image); + } else { + subscriber.onNext(returnErrorImage ? + new BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.image_not_loaded)) : + ImageUtils.getTransparent1x1Drawable(resources)); + } + subscriber.onCompleted(); + } + }); } }); } + @SuppressWarnings("static-method") + protected ImmutablePair<BitmapDrawable, Boolean> scaleImage(final ImmutablePair<Bitmap, Boolean> loadResult) { + final Bitmap bitmap = loadResult.left; + return ImmutablePair.of(bitmap != null ? ImageUtils.scaleBitmapToFitDisplay(bitmap) : null, loadResult.right); + } + public Observable<String> waitForEndObservable(@Nullable final CancellableHandler handler) { if (handler != null) { handler.unsubscribeIfCancelled(subscription); @@ -319,14 +354,14 @@ public class HtmlImage implements Html.ImageGetter { * @param url the image URL * @param pseudoGeocode the geocode or the shared name * @param forceKeep keep the image if it is there, without checking its freshness - * @return <code>true</code> if the image was there and is fresh enough, <code>false</code> otherwise + * @return A pair whose first element is the bitmap if available, and the second one is <code>true</code> if the image is present and fresh enough. */ @NonNull - private Pair<Bitmap, Boolean> loadImageFromStorage(final String url, final String pseudoGeocode, final boolean forceKeep) { + private ImmutablePair<Bitmap, Boolean> loadImageFromStorage(final String url, @NonNull final String pseudoGeocode, final boolean forceKeep) { try { final File file = LocalStorage.getStorageFile(pseudoGeocode, url, true, false); - final Pair<Bitmap, Boolean> image = loadCachedImage(file, forceKeep); - if (image.getRight() || image.getLeft() != null) { + final ImmutablePair<Bitmap, Boolean> image = loadCachedImage(file, forceKeep); + if (image.right || image.left != null) { return image; } final File fileSec = LocalStorage.getStorageSecFile(pseudoGeocode, url, true); @@ -334,7 +369,7 @@ public class HtmlImage implements Html.ImageGetter { } catch (final Exception e) { Log.w("HtmlImage.loadImageFromStorage", e); } - return new ImmutablePair<>(null, false); + return ImmutablePair.of((Bitmap) null, false); } @Nullable @@ -366,17 +401,17 @@ public class HtmlImage implements Html.ImageGetter { * * @param file the file on disk * @param forceKeep keep the image if it is there, without checking its freshness - * @return a pair with <code>true</code> if the image was there and is fresh enough or <code>false</code> otherwise, - * and the image (possibly <code>null</code> if the first component is <code>false</code> and the image - * could not be loaded, or if the first component is <code>true</code> and <code>onlySave</code> is also + * @return a pair with <code>true</code> in the second component if the image was there and is fresh enough or <code>false</code> otherwise, + * and the image (possibly <code>null</code> if the second component is <code>false</code> and the image + * could not be loaded, or if the second component is <code>true</code> and <code>onlySave</code> is also * <code>true</code>) */ @NonNull - private Pair<Bitmap, Boolean> loadCachedImage(final File file, final boolean forceKeep) { + private ImmutablePair<Bitmap, Boolean> loadCachedImage(final File file, final boolean forceKeep) { if (file.exists()) { - final boolean freshEnough = listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (new Date().getTime() - (24 * 60 * 60 * 1000)) || forceKeep; - if (onlySave) { - return new ImmutablePair<>(null, true); + final boolean freshEnough = listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (System.currentTimeMillis() - (24 * 60 * 60 * 1000)) || forceKeep; + if (freshEnough && onlySave) { + return ImmutablePair.of((Bitmap) null, true); } final BitmapFactory.Options bfOptions = new BitmapFactory.Options(); bfOptions.inTempStorage = new byte[16 * 1024]; @@ -385,12 +420,11 @@ public class HtmlImage implements Html.ImageGetter { final Bitmap image = BitmapFactory.decodeFile(file.getPath(), bfOptions); if (image == null) { Log.e("Cannot decode bitmap from " + file.getPath()); - return new ImmutablePair<>(null, false); + return ImmutablePair.of((Bitmap) null, false); } - return new ImmutablePair<>(image, - freshEnough); + return ImmutablePair.of(image, freshEnough); } - return new ImmutablePair<>(null, false); + return ImmutablePair.of((Bitmap) null, false); } private void setSampleSize(final File file, final BitmapFactory.Options bfOptions) { diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index a49b302..7eb6f61 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -1,7 +1,9 @@ package cgeo.geocaching.network; +import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; @@ -26,11 +28,12 @@ import ch.boye.httpclientandroidlib.params.CoreConnectionPNames; import ch.boye.httpclientandroidlib.params.CoreProtocolPNames; import ch.boye.httpclientandroidlib.params.HttpParams; import ch.boye.httpclientandroidlib.util.EntityUtils; + +import com.fasterxml.jackson.databind.node.ObjectNode; + import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.Nullable; -import org.json.JSONException; -import org.json.JSONObject; import android.content.Context; import android.net.ConnectivityManager; @@ -43,6 +46,7 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.regex.Pattern; public abstract class Network { @@ -51,25 +55,25 @@ public abstract class Network { /** Native user agent, taken from a Android 2.2 Nexus **/ private final static String NATIVE_USER_AGENT = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"; - private static final String PATTERN_PASSWORD = "(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"; + private static final Pattern PATTERN_PASSWORD = Pattern.compile("(?<=[\\?&])[Pp]ass(w(or)?d)?=[^&#$]+"); - private final static HttpParams clientParams = new BasicHttpParams(); + private final static HttpParams CLIENT_PARAMS = new BasicHttpParams(); static { - clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, CharEncoding.UTF_8); - clientParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000); - clientParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, 90000); - clientParams.setParameter(ClientPNames.HANDLE_REDIRECTS, true); + CLIENT_PARAMS.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, CharEncoding.UTF_8); + CLIENT_PARAMS.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000); + CLIENT_PARAMS.setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000); + CLIENT_PARAMS.setParameter(ClientPNames.HANDLE_REDIRECTS, true); } private static String hidePassword(final String message) { - return message.replaceAll(PATTERN_PASSWORD, "password=***"); + return PATTERN_PASSWORD.matcher(message).replaceAll("password=***"); } private static HttpClient getHttpClient() { final DefaultHttpClient client = new DefaultHttpClient(); client.setCookieStore(Cookies.cookieStore); - client.setParams(clientParams); + client.setParams(CLIENT_PARAMS); client.setRedirectStrategy(new LaxRedirectStrategy()); return new DecompressingHttpClient(client); } @@ -91,7 +95,7 @@ public abstract class Network { * * @param uri the URI to request * @param params the parameters to add to the POST request - * @params headers the headers to add to the request + * @param headers the headers to add to the request * @return the HTTP response, or null in case of an encoding error params */ @Nullable @@ -107,14 +111,14 @@ public abstract class Network { * @return the HTTP response, or null in case of an encoding error params */ @Nullable - public static HttpResponse postJsonRequest(final String uri, final JSONObject json) { - HttpPost request = new HttpPost(uri); + public static HttpResponse postJsonRequest(final String uri, final ObjectNode json) { + final HttpPost request = new HttpPost(uri); request.addHeader("Content-Type", "application/json; charset=utf-8"); if (json != null) { try { request.setEntity(new StringEntity(json.toString(), CharEncoding.UTF_8)); - } catch (UnsupportedEncodingException e) { - Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException"); + } catch (final UnsupportedEncodingException e) { + Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException", e); return null; } } @@ -170,7 +174,7 @@ public abstract class Network { @Nullable private static HttpResponse request(final String method, final String uri, @Nullable final Parameters params, @Nullable final Parameters headers, @Nullable final File cacheFile) { - HttpRequestBase request; + final HttpRequestBase request; if (method.equals("GET")) { final String fullUri = params == null ? uri : Uri.parse(uri).buildUpon().encodedQuery(params.toString()).build().toString(); request = new HttpGet(fullUri); @@ -221,6 +225,10 @@ public abstract class Network { */ @Nullable private static HttpResponse doLogRequest(final HttpRequestBase request) { + if (!isNetworkConnected()) { + return null; + } + final String reqLogStr = request.getMethod() + " " + hidePassword(request.getURI().toString()); Log.d(reqLogStr); @@ -228,7 +236,7 @@ public abstract class Network { final long before = System.currentTimeMillis(); try { final HttpResponse response = client.execute(request); - int status = response.getStatusLine().getStatusCode(); + final int status = response.getStatusLine().getStatusCode(); if (status == 200) { Log.d(status + formatTimeSpan(before) + reqLogStr); } else { @@ -344,14 +352,14 @@ public abstract class Network { * @return a JSON object if the request was successful and the body could be decoded, <code>null</code> otherwise */ @Nullable - public static JSONObject requestJSON(final String uri, @Nullable final Parameters params) { + public static ObjectNode requestJSON(final String uri, @Nullable final Parameters params) { final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null); final String responseData = getResponseData(response, false); if (responseData != null) { try { - return new JSONObject(responseData); - } catch (final JSONException e) { - Log.w("Network.requestJSON", e); + return (ObjectNode) JsonUtils.reader.readTree(responseData); + } catch (final IOException e) { + Log.w("requestJSON", e); } } @@ -369,7 +377,7 @@ public abstract class Network { if (!isSuccess(response)) { return null; } - assert(response != null); + assert response != null; final HttpEntity entity = response.getEntity(); if (entity == null) { return null; @@ -383,11 +391,11 @@ public abstract class Network { } @Nullable - private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) { + private static String getResponseDataNoError(final HttpResponse response, final boolean replaceWhitespace) { try { - String data = EntityUtils.toString(response.getEntity(), CharEncoding.UTF_8); + final String data = EntityUtils.toString(response.getEntity(), CharEncoding.UTF_8); return replaceWhitespace ? TextUtils.replaceWhitespace(data) : data; - } catch (Exception e) { + } catch (final Exception e) { Log.e("getResponseData", e); return null; } @@ -420,7 +428,7 @@ public abstract class Network { * @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise */ @Nullable - public static String getResponseData(@Nullable final HttpResponse response, boolean replaceWhitespace) { + public static String getResponseData(@Nullable final HttpResponse response, final boolean replaceWhitespace) { if (!isSuccess(response)) { return null; } @@ -429,7 +437,7 @@ public abstract class Network { } @Nullable - public static String rfc3986URLEncode(String text) { + public static String rfc3986URLEncode(final String text) { final String encoded = encode(text); return encoded != null ? StringUtils.replace(encoded.replace("+", "%20"), "%7E", "~") : null; } @@ -438,7 +446,7 @@ public abstract class Network { public static String decode(final String text) { try { return URLDecoder.decode(text, CharEncoding.UTF_8); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { Log.e("Network.decode", e); } return null; @@ -448,25 +456,26 @@ public abstract class Network { public static String encode(final String text) { try { return URLEncoder.encode(text, CharEncoding.UTF_8); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { Log.e("Network.encode", e); } return null; } + private static ConnectivityManager connectivityManager = null; + /** * Checks if the device has network connection. * - * @param context - * context of the application, cannot be null - * * @return <code>true</code> if the device is connected to the network. */ - public static boolean isNetworkConnected(Context context) { - ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = conMan.getActiveNetworkInfo(); - - return activeNetwork != null && activeNetwork.isConnected(); + public static boolean isNetworkConnected() { + if (connectivityManager == null) { + // Concurrent assignment would not hurt + connectivityManager = (ConnectivityManager) CgeoApplication.getInstance().getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); + } + final NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); + return activeNetworkInfo != null && activeNetworkInfo.isConnected(); } } diff --git a/main/src/cgeo/geocaching/network/OAuth.java b/main/src/cgeo/geocaching/network/OAuth.java index cfc62fc..4f1fcc0 100644 --- a/main/src/cgeo/geocaching/network/OAuth.java +++ b/main/src/cgeo/geocaching/network/OAuth.java @@ -6,10 +6,8 @@ import ch.boye.httpclientandroidlib.NameValuePair; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import java.util.ArrayList; -import java.util.Date; import java.util.List; public class OAuth { @@ -18,16 +16,15 @@ public class OAuth { final String method, final boolean https, final Parameters params, - @Nullable final String token, - @Nullable final String tokenSecret, + final OAuthTokens tokens, final String consumerKey, final String consumerSecret) { params.put( "oauth_consumer_key", consumerKey, "oauth_nonce", CryptUtils.md5(Long.toString(System.currentTimeMillis())), "oauth_signature_method", "HMAC-SHA1", - "oauth_timestamp", Long.toString(new Date().getTime() / 1000), - "oauth_token", StringUtils.defaultString(token), + "oauth_timestamp", Long.toString(System.currentTimeMillis() / 1000), + "oauth_token", StringUtils.defaultString(tokens.getTokenPublic()), "oauth_version", "1.0"); params.sort(); @@ -36,19 +33,16 @@ public class OAuth { paramsEncoded.add(nameValue.getName() + "=" + OAuth.percentEncode(nameValue.getValue())); } - final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokenSecret); // both even if empty some of them! + final String keysPacked = consumerSecret + "&" + StringUtils.defaultString(tokens.getTokenSecret()); // both even if empty some of them! final @NonNull String joinedParams = StringUtils.join(paramsEncoded.toArray(), '&'); final String requestPacked = method + "&" + OAuth.percentEncode((https ? "https" : "http") + "://" + host + path) + "&" + OAuth.percentEncode(joinedParams); params.put("oauth_signature", CryptUtils.base64Encode(CryptUtils.hashHmac(requestPacked, keysPacked))); } /** - * percent encode following http://tools.ietf.org/html/rfc5849#section-3.6 - * - * @param url - * @return + * Percent encode following http://tools.ietf.org/html/rfc5849#section-3.6 */ - static String percentEncode(@NonNull String url) { + static String percentEncode(@NonNull final String url) { return StringUtils.replace(Network.rfc3986URLEncode(url), "*", "%2A"); } } diff --git a/main/src/cgeo/geocaching/network/OAuthTokens.java b/main/src/cgeo/geocaching/network/OAuthTokens.java new file mode 100644 index 0000000..9f45e7f --- /dev/null +++ b/main/src/cgeo/geocaching/network/OAuthTokens.java @@ -0,0 +1,38 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.connector.oc.OCApiConnector; +import cgeo.geocaching.settings.Settings; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.eclipse.jdt.annotation.NonNull; + +import android.util.Pair; + +public class OAuthTokens extends Pair<String, String> { + + public OAuthTokens(@NonNull final OCApiConnector connector) { + this(Settings.getTokenPair(connector.getTokenPublicPrefKeyId(), connector.getTokenSecretPrefKeyId())); + } + + public OAuthTokens(final ImmutablePair<String, String> tokenPair) { + this(tokenPair.left, tokenPair.right); + } + + public OAuthTokens(final String pub, final String secret) { + super(pub, secret); + } + + public boolean isValid() { + return StringUtils.isNotBlank(getTokenPublic()) && StringUtils.isNotBlank(getTokenSecret()); + } + + public String getTokenPublic() { + return first; + } + + public String getTokenSecret() { + return second; + } + +} diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java index 9cb0da5..d6285da 100644 --- a/main/src/cgeo/geocaching/network/Parameters.java +++ b/main/src/cgeo/geocaching/network/Parameters.java @@ -3,6 +3,7 @@ package cgeo.geocaching.network; import ch.boye.httpclientandroidlib.NameValuePair; import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils; import ch.boye.httpclientandroidlib.message.BasicNameValuePair; + import org.apache.commons.lang3.CharEncoding; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; diff --git a/main/src/cgeo/geocaching/network/Send2CgeoDownloader.java b/main/src/cgeo/geocaching/network/Send2CgeoDownloader.java new file mode 100644 index 0000000..5f5be56 --- /dev/null +++ b/main/src/cgeo/geocaching/network/Send2CgeoDownloader.java @@ -0,0 +1,70 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.RxUtils; + +import ch.boye.httpclientandroidlib.HttpResponse; + +import org.apache.commons.lang3.StringUtils; + +import rx.Scheduler.Worker; +import rx.functions.Action0; + +import java.util.concurrent.TimeUnit; + +public class Send2CgeoDownloader { + + private Send2CgeoDownloader() { + // Do not instantiate + } + + /** + * Asynchronously load caches from the send2cgeo server. + * + * @param handler the handler to which progress information will be sent + * @param listId the list into which caches will be stored + */ + public static void loadFromWeb(final CancellableHandler handler, final int listId) { + final Worker worker = RxUtils.networkScheduler.createWorker(); + handler.unsubscribeIfCancelled(worker); + worker.schedule(new Action0() { + private final Parameters PARAMS = new Parameters("code", StringUtils.defaultString(Settings.getWebDeviceCode())); + private long baseTime = System.currentTimeMillis(); + + @Override + public void call() { + if (System.currentTimeMillis() - baseTime >= 3 * 60000) { // maximum: 3 minutes + handler.sendEmptyMessage(DownloadProgress.MSG_DONE); + return; + } + + // Download new code + final HttpResponse responseFromWeb = Network.getRequest("http://send2.cgeo.org/read.html", PARAMS); + + if (responseFromWeb != null && responseFromWeb.getStatusLine().getStatusCode() == 200) { + final String response = Network.getResponseData(responseFromWeb); + if (response != null && response.length() > 2) { + handler.sendMessage(handler.obtainMessage(DownloadProgress.MSG_LOADING, response)); + Geocache.storeCache(null, response, listId, false, null); + handler.sendMessage(handler.obtainMessage(DownloadProgress.MSG_LOADED, response)); + baseTime = System.currentTimeMillis(); + worker.schedule(this); + } else if ("RG".equals(response)) { + //Server returned RG (registration) and this device no longer registered. + Settings.setWebNameCode(null, null); + handler.sendEmptyMessage(DownloadProgress.MSG_NO_REGISTRATION); + handler.cancel(); + } else { + worker.schedule(this, 5, TimeUnit.SECONDS); + handler.sendEmptyMessage(DownloadProgress.MSG_WAITING); + } + } else { + handler.sendEmptyMessage(DownloadProgress.MSG_SERVER_FAIL); + handler.cancel(); + } + } + }); + } +} diff --git a/main/src/cgeo/geocaching/network/SmileyImage.java b/main/src/cgeo/geocaching/network/SmileyImage.java new file mode 100644 index 0000000..9bb811e --- /dev/null +++ b/main/src/cgeo/geocaching/network/SmileyImage.java @@ -0,0 +1,40 @@ +package cgeo.geocaching.network; + +import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.utils.ImageUtils; +import cgeo.geocaching.utils.ImageUtils.LineHeightContainerDrawable; + +import org.apache.commons.lang3.tuple.ImmutablePair; + +import rx.Observable; + +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.widget.TextView; + +/** + * Specialized image class for fetching and displaying smileys in the log book. + */ +public class SmileyImage extends HtmlImage { + + public SmileyImage(final String geocode, final TextView view) { + super(geocode, false, StoredList.STANDARD_LIST_ID, false, view); + } + + @Override + protected ImmutablePair<BitmapDrawable, Boolean> scaleImage(final ImmutablePair<Bitmap, Boolean> loadResult) { + final Bitmap bitmap = loadResult.left; + if (bitmap == null) { + return ImmutablePair.of((BitmapDrawable) null, loadResult.right); + } + final BitmapDrawable drawable = new BitmapDrawable(view.getResources(), bitmap); + drawable.setBounds(ImageUtils.scaleImageToLineHeight(drawable, view)); + return ImmutablePair.of(drawable, loadResult.right); + } + + @Override + protected BitmapDrawable getContainerDrawable(final Observable<BitmapDrawable> drawable) { + return new LineHeightContainerDrawable(view, drawable); + } + +} diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java index 82650d1..bc4a5db 100644 --- a/main/src/cgeo/geocaching/network/StatusUpdater.java +++ b/main/src/cgeo/geocaching/network/StatusUpdater.java @@ -4,8 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.Version; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.databind.node.ObjectNode; import rx.functions.Action0; import rx.subjects.BehaviorSubject; @@ -31,11 +30,11 @@ public class StatusUpdater { this.url = url; } - Status(final JSONObject response) { - message = get(response, "message"); - messageId = get(response, "message_id"); - icon = get(response, "icon"); - url = get(response, "url"); + Status(final ObjectNode response) { + message = response.path("message").asText(null); + messageId = response.path("message_id").asText(null); + icon = response.path("icon").asText(null); + url = response.path("url").asText(null); } final static public Status closeoutStatus = @@ -55,7 +54,7 @@ public class StatusUpdater { RxUtils.networkScheduler.createWorker().schedulePeriodically(new Action0() { @Override public void call() { - final JSONObject response = + final ObjectNode response = Network.requestJSON("http://status.cgeo.org/api/status.json", new Parameters("version_code", String.valueOf(Version.getVersionCode(CgeoApplication.getInstance())), "version_name", Version.getVersionName(CgeoApplication.getInstance()), @@ -67,12 +66,4 @@ public class StatusUpdater { }, 0, 1800, TimeUnit.SECONDS); } - private static String get(final JSONObject json, final String key) { - try { - return json.getString(key); - } catch (final JSONException e) { - return null; - } - } - } diff --git a/main/src/cgeo/geocaching/playservices/LocationProvider.java b/main/src/cgeo/geocaching/playservices/LocationProvider.java new file mode 100644 index 0000000..027ae29 --- /dev/null +++ b/main/src/cgeo/geocaching/playservices/LocationProvider.java @@ -0,0 +1,160 @@ +package cgeo.geocaching.playservices; + +import cgeo.geocaching.sensors.GeoData; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.location.LocationListener; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationServices; + +import rx.Observable; +import rx.Observable.OnSubscribe; +import rx.Subscriber; +import rx.functions.Action0; +import rx.functions.Func1; +import rx.observers.Subscribers; +import rx.subjects.ReplaySubject; +import rx.subscriptions.Subscriptions; + +import android.content.Context; +import android.location.Location; +import android.os.Bundle; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class LocationProvider implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { + + private static final LocationRequest LOCATION_REQUEST = + LocationRequest.create().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(2000).setFastestInterval(250); + private static final LocationRequest LOCATION_REQUEST_LOW_POWER = + LocationRequest.create().setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY).setInterval(10000).setFastestInterval(5000); + private static final AtomicInteger mostPreciseCount = new AtomicInteger(0); + private static final AtomicInteger lowPowerCount = new AtomicInteger(0); + private static LocationProvider instance = null; + private static final ReplaySubject<GeoData> subject = ReplaySubject.createWithSize(1); + private final GoogleApiClient locationClient; + + private static synchronized LocationProvider getInstance(final Context context) { + if (instance == null) { + instance = new LocationProvider(context); + } + return instance; + } + + private synchronized void updateRequest() { + if (locationClient.isConnected()) { + if (mostPreciseCount.get() > 0) { + Log.d("LocationProvider: requesting most precise locations"); + LocationServices.FusedLocationApi.requestLocationUpdates(locationClient, LOCATION_REQUEST, this, RxUtils.looperCallbacksLooper); + } else if (lowPowerCount.get() > 0) { + Log.d("LocationProvider: requesting low-power locations"); + LocationServices.FusedLocationApi.requestLocationUpdates(locationClient, LOCATION_REQUEST_LOW_POWER, this, RxUtils.looperCallbacksLooper); + } else { + Log.d("LocationProvider: stopping location requests"); + LocationServices.FusedLocationApi.removeLocationUpdates(locationClient, this); + } + } + } + + private static Observable<GeoData> get(final Context context, final AtomicInteger reference) { + final LocationProvider instance = getInstance(context); + return Observable.create(new OnSubscribe<GeoData>() { + @Override + public void call(final Subscriber<? super GeoData> subscriber) { + if (reference.incrementAndGet() == 1) { + instance.updateRequest(); + } + subscriber.add(Subscriptions.create(new Action0() { + @Override + public void call() { + RxUtils.looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (reference.decrementAndGet() == 0) { + instance.updateRequest(); + } + } + }, 2500, TimeUnit.MILLISECONDS); + } + })); + subscriber.add(subject.subscribe(Subscribers.from(subscriber))); + } + }); + } + + public static Observable<GeoData> getMostPrecise(final Context context) { + return get(context, mostPreciseCount).onBackpressureDrop(); + } + + public static Observable<GeoData> getLowPower(final Context context) { + // Low-power location without the last stored location + final Observable<GeoData> lowPowerObservable = get(context, lowPowerCount).skip(1); + + // High-power location without the last stored location + final Observable<GeoData> highPowerObservable = get(context, mostPreciseCount).skip(1); + + // Use either low-power (with a 6 seconds head start) or high-power observables to obtain a location + // no less precise than 20 meters. + final Observable<GeoData> untilPreciseEnoughObservable = + lowPowerObservable.mergeWith(highPowerObservable.delaySubscription(6, TimeUnit.SECONDS)) + .takeUntil(new Func1<GeoData, Boolean>() { + @Override + public Boolean call(final GeoData geoData) { + return geoData.getAccuracy() <= 20; + } + }); + + // After sending the last known location, try to get a precise location then use the low-power mode. If no + // location information is given for 25 seconds (if the network location is turned off for example), get + // back to the precise location and try again. + return subject.first().concatWith(untilPreciseEnoughObservable.concatWith(lowPowerObservable).timeout(25, TimeUnit.SECONDS).retry()).onBackpressureDrop(); + } + + /** + * Build a new geo data provider object. + * <p/> + * There is no need to instantiate more than one such object in an application, as observers can be added + * at will. + * + * @param context the context used to retrieve the system services + */ + private LocationProvider(final Context context) { + final GeoData initialLocation = GeoData.getInitialLocation(context); + subject.onNext(initialLocation != null ? initialLocation : GeoData.DUMMY_LOCATION); + locationClient = new GoogleApiClient.Builder(context) + .addApi(LocationServices.API) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .build(); + locationClient.connect(); + } + + @Override + public void onConnected(final Bundle bundle) { + updateRequest(); + } + + @Override + public void onConnectionFailed(final ConnectionResult connectionResult) { + Log.e("cannot connect to Google Play location service: " + connectionResult); + subject.onError(new RuntimeException("Connection failed: " + connectionResult)); + } + + @Override + public void onLocationChanged(final Location location) { + if (Settings.useLowPowerMode()) { + location.setProvider(GeoData.LOW_POWER_PROVIDER); + } + subject.onNext(new GeoData(location)); + } + + @Override + public void onConnectionSuspended(final int arg0) { + // empty + } +} diff --git a/main/src/cgeo/geocaching/sensors/DirectionProvider.java b/main/src/cgeo/geocaching/sensors/DirectionProvider.java deleted file mode 100644 index ed5d76a..0000000 --- a/main/src/cgeo/geocaching/sensors/DirectionProvider.java +++ /dev/null @@ -1,146 +0,0 @@ -package cgeo.geocaching.sensors; - -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.utils.AngleUtils; -import cgeo.geocaching.utils.StartableHandlerThread; - -import rx.Observable; -import rx.Observable.OnSubscribe; -import rx.Subscriber; -import rx.subjects.BehaviorSubject; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.os.Handler; -import android.os.Process; -import android.view.Surface; -import android.view.WindowManager; - -public class DirectionProvider { - - private static final BehaviorSubject<Float> SUBJECT = BehaviorSubject.create(0.0f); - - private static final WindowManager WINDOW_MANAGER = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); - - private DirectionProvider() { - // utility class - } - - static class Listener implements SensorEventListener, StartableHandlerThread.Callback { - - private int count = 0; - - private SensorManager sensorManager; - - @Override - public void onSensorChanged(final SensorEvent event) { - SUBJECT.onNext(event.values[0]); - } - - @Override - public void onAccuracyChanged(final Sensor sensor, final int accuracy) { - /* - * There is a bug in Android, which apparently causes this method to be called every - * time the sensor _value_ changed, even if the _accuracy_ did not change. Do not have any code in here. - * - * See for example https://code.google.com/p/android/issues/detail?id=14792 - */ - } - - @Override - public void start(final Context context, final Handler handler) { - if (!hasSensor(context)) { - return; - } - if (++count == 1) { - Sensor orientationSensor = getOrientationSensor(context); - sensorManager.registerListener(this, orientationSensor, SensorManager.SENSOR_DELAY_NORMAL, handler); - } - } - - @Override - public void stop() { - if (!hasSensor) { - return; - } - if (--count == 0) { - sensorManager.unregisterListener(this); - } - } - - /** - * Assume that there is an orientation sensor, unless we have really checked that - */ - private boolean hasSensor = true; - - /** - * Flag for one time check if there is a sensor. - */ - private boolean hasSensorChecked = false; - - public boolean hasSensor(Context context) { - if (!hasSensorChecked) { - hasSensor = getOrientationSensor(context) != null; - hasSensorChecked = true; - } - return hasSensor; - } - - // This will be removed when using a new location service. Until then, it is okay to be used. - @SuppressWarnings("deprecation") - private Sensor getOrientationSensor(final Context context) { - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - return sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); - } - - } - - private static final StartableHandlerThread HANDLER_THREAD = - new StartableHandlerThread("DirectionProvider thread", Process.THREAD_PRIORITY_BACKGROUND, new Listener()); - - static { - HANDLER_THREAD.start(); - } - - public static Observable<Float> create(final Context context) { - return Observable.create(new OnSubscribe<Float>() { - @Override - public void call(final Subscriber<? super Float> subscriber) { - HANDLER_THREAD.start(subscriber, context); - SUBJECT.subscribe(subscriber); - } - }); - } - - /** - * Take the phone rotation (through a given activity) in account and adjust the direction. - * - * @param direction the unadjusted direction in degrees, in the [0, 360[ range - * @return the adjusted direction in degrees, in the [0, 360[ range - */ - - public static float getDirectionNow(final float direction) { - return AngleUtils.normalize(direction + getRotationOffset()); - } - - static float reverseDirectionNow(final float direction) { - return AngleUtils.normalize(direction - getRotationOffset()); - } - - private static int getRotationOffset() { - switch (WINDOW_MANAGER.getDefaultDisplay().getRotation()) { - case Surface.ROTATION_90: - return 90; - case Surface.ROTATION_180: - return 180; - case Surface.ROTATION_270: - return 270; - default: - return 0; - } - } - -} diff --git a/main/src/cgeo/geocaching/sensors/GeoData.java b/main/src/cgeo/geocaching/sensors/GeoData.java index c0b3974..b8b16fd 100644 --- a/main/src/cgeo/geocaching/sensors/GeoData.java +++ b/main/src/cgeo/geocaching/sensors/GeoData.java @@ -1,67 +1,109 @@ package cgeo.geocaching.sensors; -import cgeo.geocaching.enumerations.LocationProviderType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.Log; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import android.content.Context; import android.location.Location; import android.location.LocationManager; -class GeoData extends Location implements IGeoData { - private final boolean gpsEnabled; - private final int satellitesVisible; - private final int satellitesFixed; - private final boolean pseudoLocation; +public class GeoData extends Location { - GeoData(final Location location, final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed, final boolean pseudoLocation) { - super(location); - this.gpsEnabled = gpsEnabled; - this.satellitesVisible = satellitesVisible; - this.satellitesFixed = satellitesFixed; - this.pseudoLocation = pseudoLocation; + public static final String INITIAL_PROVIDER = "initial"; + public static final String HOME_PROVIDER = "home"; + public static final String FUSED_PROVIDER = "fused"; + public static final String LOW_POWER_PROVIDER = "low-power"; + + // Some devices will not have the last position available (for example the emulator). In this case, + // rather than waiting forever for a position update which might never come, we emulate it by placing + // the user arbitrarly at Paris Notre-Dame, one of the most visited free tourist attractions in the world. + final public static GeoData DUMMY_LOCATION = new GeoData(new Location(INITIAL_PROVIDER)); + + static { + DUMMY_LOCATION.setLatitude(48.85308); + DUMMY_LOCATION.setLongitude(2.34962); } - @Override - public Location getLocation() { - return this; + public GeoData(final Location location) { + super(location); } - private static LocationProviderType getLocationProviderType(final String provider) { - if (provider.equals(LocationManager.GPS_PROVIDER)) { - return LocationProviderType.GPS; + @Nullable + static Location best(@Nullable final Location gpsLocation, @Nullable final Location netLocation) { + if (netLocation == null || (gpsLocation != null && System.currentTimeMillis() <= gpsLocation.getTime() + 30000)) { + return gpsLocation; } - if (provider.equals(LocationManager.NETWORK_PROVIDER)) { - return LocationProviderType.NETWORK; + if (gpsLocation == null) { + return netLocation; } - return LocationProviderType.LAST; + return gpsLocation.getTime() >= netLocation.getTime() ? gpsLocation : netLocation; } - @Override public LocationProviderType getLocationProvider() { - return getLocationProviderType(getProvider()); + switch (getProvider()) { + case LocationManager.GPS_PROVIDER: + return LocationProviderType.GPS; + case LocationManager.NETWORK_PROVIDER: + return LocationProviderType.NETWORK; + case FUSED_PROVIDER: + // LocationManager.FUSED_PROVIDER constant is not available at API level 9 + return LocationProviderType.FUSED; + case LOW_POWER_PROVIDER: + return LocationProviderType.LOW_POWER; + case HOME_PROVIDER: + return LocationProviderType.HOME; + default: + return LocationProviderType.LAST; + } } - @Override + @NonNull public Geopoint getCoords() { return new Geopoint(this); } - @Override - public boolean getGpsEnabled() { - return gpsEnabled; - } - - @Override - public int getSatellitesVisible() { - return satellitesVisible; - } - - @Override - public int getSatellitesFixed() { - return satellitesFixed; + @Nullable + public static GeoData getInitialLocation(final Context context) { + final LocationManager geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + if (geoManager != null) { + try { + // Try to find a sensible initial location from the last locations known to Android. + final Location lastGpsLocation = geoManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + final Location lastNetworkLocation = geoManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); + final Location bestLocation = best(lastGpsLocation, lastNetworkLocation); + if (bestLocation != null) { + bestLocation.setProvider(INITIAL_PROVIDER); + return new GeoData(bestLocation); + } + } catch (final Exception e) { + // This error is non-fatal as its only consequence is that we will start with a dummy location + // instead of a previously known one. + Log.e("Error when retrieving last known location", e); + } + } else { + Log.w("No LocationManager available"); + } + final String homeLocationStr = Settings.getHomeLocation(); + if (StringUtils.isNotBlank(homeLocationStr)) { + try { + assert homeLocationStr != null; + final Geopoint homeLocation = new Geopoint(homeLocationStr); + Log.i("No last known location available, using home location"); + final Location initialLocation = new Location(HOME_PROVIDER); + initialLocation.setLatitude(homeLocation.getLatitude()); + initialLocation.setLongitude(homeLocation.getLongitude()); + return new GeoData(initialLocation); + } catch (final Geopoint.ParseException e) { + Log.w("Unable to parse home location " + homeLocationStr, e); + } + } + Log.i("No last known location nor home location available"); + return null; } - @Override - public boolean isPseudoLocation() { - return pseudoLocation; - } -} +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java index a4799cb..dab05d0 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDataProvider.java +++ b/main/src/cgeo/geocaching/sensors/GeoDataProvider.java @@ -1,25 +1,13 @@ package cgeo.geocaching.sensors; import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.StartableHandlerThread; +import cgeo.geocaching.utils.RxUtils.LooperCallbacks; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.Observable.OnSubscribe; -import rx.Subscriber; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action0; -import rx.functions.Action1; -import rx.observables.ConnectableObservable; -import rx.subjects.BehaviorSubject; -import rx.subscriptions.CompositeSubscription; -import rx.subscriptions.Subscriptions; import android.content.Context; -import android.location.GpsSatellite; -import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; @@ -27,40 +15,13 @@ import android.os.Bundle; import java.util.concurrent.TimeUnit; -public class GeoDataProvider implements OnSubscribe<IGeoData> { +public class GeoDataProvider extends LooperCallbacks<GeoData> { - private static final String LAST_LOCATION_PSEUDO_PROVIDER = "last"; + private final Context context; private final LocationManager geoManager; - private final LocationData gpsLocation = new LocationData(); - private final LocationData netLocation = new LocationData(); - private final BehaviorSubject<IGeoData> subject; - private static final StartableHandlerThread handlerThread = - new StartableHandlerThread("GeoDataProvider thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); - static { - handlerThread.start(); - } - - public boolean gpsEnabled = false; - public int satellitesVisible = 0; - public int satellitesFixed = 0; - - private static class LocationData { - public Location location; - public long timestamp = 0; - - public void update(final Location location) { - this.location = location; - timestamp = System.currentTimeMillis(); - } - - public boolean isRecent() { - return isValid() && System.currentTimeMillis() < timestamp + 30000; - } - - public boolean isValid() { - return location != null; - } - } + private Location latestGPSLocation = null; + private final Listener networkListener = new Listener(); + private final Listener gpsListener = new Listener(); /** * Build a new geo data provider object. @@ -71,117 +32,51 @@ public class GeoDataProvider implements OnSubscribe<IGeoData> { * @param context the context used to retrieve the system services */ protected GeoDataProvider(final Context context) { - geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - subject = BehaviorSubject.create(findInitialLocation()); + super(2500, TimeUnit.MILLISECONDS); + this.context = context.getApplicationContext(); + geoManager = (LocationManager) this.context.getSystemService(Context.LOCATION_SERVICE); } - public static Observable<IGeoData> create(final Context context) { - final GeoDataProvider provider = new GeoDataProvider(context); - return provider.worker.refCount(); + public static Observable<GeoData> create(final Context context) { + return Observable.create(new GeoDataProvider(context)).onBackpressureDrop(); } @Override - public void call(final Subscriber<? super IGeoData> subscriber) { - subject.subscribe(subscriber); - } - - final ConnectableObservable<IGeoData> worker = new ConnectableObservable<IGeoData>(this) { - private int debugSessionCounter = 0; - - private final Object lock = new Object(); - private int count = 0; - - final private GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); - final private Listener networkListener = new Listener(LocationManager.NETWORK_PROVIDER, netLocation); - final private Listener gpsListener = new Listener(LocationManager.GPS_PROVIDER, gpsLocation); - - @Override - public void connect(Action1<? super Subscription> connection) { - final CompositeSubscription subscription = new CompositeSubscription(); - AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { - @Override - public void call() { - synchronized(lock) { - if (count++ == 0) { - Log.d("GeoDataProvider: starting the GPS and network listeners" + " (" + ++debugSessionCounter + ")"); - geoManager.addGpsStatusListener(gpsStatusListener); - for (final Listener listener : new Listener[] { networkListener, gpsListener }) { - try { - geoManager.requestLocationUpdates(listener.locationProvider, 0, 0, listener); - } catch (final Exception e) { - Log.w("There is no location provider " + listener.locationProvider); - } - } - } - } - - subscription.add(Subscriptions.create(new Action0() { - @Override - public void call() { - AndroidSchedulers.handlerThread(handlerThread.getHandler()).createWorker().schedule(new Action0() { - @Override - public void call() { - synchronized (lock) { - if (--count == 0) { - Log.d("GeoDataProvider: stopping the GPS and network listeners" + " (" + debugSessionCounter + ")"); - geoManager.removeUpdates(networkListener); - geoManager.removeUpdates(gpsListener); - geoManager.removeGpsStatusListener(gpsStatusListener); - } - } - } - }, 2500, TimeUnit.MILLISECONDS); - } - })); - } - }); - connection.call(subscription); + public void onStart() { + final GeoData initialLocation = GeoData.getInitialLocation(context); + if (initialLocation != null) { + subject.onNext(initialLocation); } - }; - - private IGeoData findInitialLocation() { - final Location initialLocation = new Location(LAST_LOCATION_PSEUDO_PROVIDER); + Log.d("GeoDataProvider: starting the GPS and network listeners"); try { - // Try to find a sensible initial location from the last locations known to Android. - final Location lastGpsLocation = geoManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); - final Location lastNetworkLocation = geoManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); - - // If both providers are non-null, take the most recent one - if (lastGpsLocation != null && lastNetworkLocation != null) { - if (lastGpsLocation.getTime() >= lastNetworkLocation.getTime()) { - copyCoords(initialLocation, lastGpsLocation); - } else { - copyCoords(initialLocation, lastNetworkLocation); - } - } else if (lastGpsLocation != null) { - copyCoords(initialLocation, lastGpsLocation); - } else if (lastNetworkLocation != null) { - copyCoords(initialLocation, lastNetworkLocation); - } else { - Log.i("GeoDataProvider: no last known location available"); - } + geoManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsListener); + } catch (final Exception e) { + Log.w("Unable to create GPS location provider: " + e.getMessage()); + } + try { + geoManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, networkListener); } catch (final Exception e) { - // This error is non-fatal as its only consequence is that we will start with a dummy location - // instead of a previously known one. - Log.e("GeoDataProvider: error when retrieving last known location", e); + Log.w("Unable to create network location provider: " + e.getMessage()); } - // Start with an historical GeoData just in case someone queries it before we get - // a chance to get any information. - return new GeoData(initialLocation, false, 0, 0, true); } - private static void copyCoords(final Location target, final Location source) { - target.setLatitude(source.getLatitude()); - target.setLongitude(source.getLongitude()); + @Override + protected void onStop() { + Log.d("GeoDataProvider: stopping the GPS and network listeners"); + geoManager.removeUpdates(networkListener); + geoManager.removeUpdates(gpsListener); } private class Listener implements LocationListener { - private final String locationProvider; - private final LocationData locationData; - Listener(final String locationProvider, final LocationData locationData) { - this.locationProvider = locationProvider; - this.locationData = locationData; + @Override + public void onLocationChanged(final Location location) { + if (StringUtils.equals(location.getProvider(), LocationManager.GPS_PROVIDER)) { + latestGPSLocation = location; + assign(latestGPSLocation); + } else { + assign(GeoData.best(latestGPSLocation, location)); + } } @Override @@ -198,85 +93,11 @@ public class GeoDataProvider implements OnSubscribe<IGeoData> { public void onProviderEnabled(final String provider) { // nothing } - - @Override - public void onLocationChanged(final Location location) { - locationData.update(location); - selectBest(); - } - } - - private final class GpsStatusListener implements GpsStatus.Listener { - - @Override - public void onGpsStatusChanged(final int event) { - boolean changed = false; - switch (event) { - case GpsStatus.GPS_EVENT_FIRST_FIX: - case GpsStatus.GPS_EVENT_SATELLITE_STATUS: { - final GpsStatus status = geoManager.getGpsStatus(null); - int visible = 0; - int fixed = 0; - for (final GpsSatellite satellite : status.getSatellites()) { - if (satellite.usedInFix()) { - fixed++; - } - visible++; - } - if (visible != satellitesVisible || fixed != satellitesFixed) { - satellitesVisible = visible; - satellitesFixed = fixed; - changed = true; - } - break; - } - case GpsStatus.GPS_EVENT_STARTED: - if (!gpsEnabled) { - gpsEnabled = true; - changed = true; - } - break; - case GpsStatus.GPS_EVENT_STOPPED: - if (gpsEnabled) { - gpsEnabled = false; - satellitesFixed = 0; - satellitesVisible = 0; - changed = true; - } - break; - default: - throw new IllegalStateException(); - } - - if (changed) { - selectBest(); - } - } - } - - private LocationData best() { - if (gpsLocation.isRecent() || !netLocation.isValid()) { - return gpsLocation.isValid() ? gpsLocation : null; - } - if (!gpsLocation.isValid()) { - return netLocation; - } - return gpsLocation.timestamp > netLocation.timestamp ? gpsLocation : netLocation; - } - - private void selectBest() { - assign(best()); } - private void assign(final LocationData locationData) { - if (locationData == null) { - return; - } - + private void assign(final Location location) { // We do not necessarily get signalled when satellites go to 0/0. - final int visible = gpsLocation.isRecent() ? satellitesVisible : 0; - final boolean pseudoLocation = StringUtils.equals(locationData.location.getProvider(), LAST_LOCATION_PSEUDO_PROVIDER); - final IGeoData current = new GeoData(locationData.location, gpsEnabled, visible, satellitesFixed, pseudoLocation); + final GeoData current = new GeoData(location); subject.onNext(current); } diff --git a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java index 0f30142..4743140 100644 --- a/main/src/cgeo/geocaching/sensors/GeoDirHandler.java +++ b/main/src/cgeo/geocaching/sensors/GeoDirHandler.java @@ -1,27 +1,25 @@ package cgeo.geocaching.sensors; -import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.settings.Settings; - import org.apache.commons.lang3.tuple.ImmutablePair; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; -import rx.functions.Func1; import rx.functions.Func2; import rx.subscriptions.CompositeSubscription; +import java.util.concurrent.TimeUnit; + /** * GeoData and Direction handler. * <p> - * To use this class, override {@link #updateGeoDir(IGeoData, float)}. You need to start the handler using + * To use this class, override {@link #updateGeoDir(cgeo.geocaching.sensors.GeoData, float)}. You need to start the handler using * {@link #start(int)}. A good place to do so might be the {@code onResume} method of the Activity. Stop the Handler * accordingly in {@code onPause}. * * The direction is always relative to the top of the device (natural direction), and that it must - * be fixed using {@link DirectionProvider#getDirectionNow(float)}. When the direction is derived from the GPS, + * be fixed using {@link cgeo.geocaching.utils.AngleUtils#getDirectionNow(float)}. When the direction is derived from the GPS, * it is altered so that the fix can still be applied as if the information came from the compass. */ public abstract class GeoDirHandler { @@ -29,8 +27,7 @@ public abstract class GeoDirHandler { public static final int UPDATE_GEODATA = 1 << 1; public static final int UPDATE_DIRECTION = 1 << 2; public static final int UPDATE_GEODIR = 1 << 3; - - private static final CgeoApplication app = CgeoApplication.getInstance(); + public static final int LOW_POWER = 1 << 4; /** * Update method called when new geodata is available. This method is called on the UI thread. @@ -38,7 +35,7 @@ public abstract class GeoDirHandler { * * @param geoData the new geographical data */ - public void updateGeoData(final IGeoData geoData) { + public void updateGeoData(final GeoData geoData) { } /** @@ -60,41 +57,46 @@ public abstract class GeoDirHandler { * If the device goes fast enough, or if the compass use is not enabled in the settings, * the GPS direction information will be used instead of the compass one. */ - public void updateGeoDir(final IGeoData geoData, final float direction) { + public void updateGeoDir(final GeoData geoData, final float direction) { } - private static Observable<Float> fixedDirection() { - return app.directionObservable().map(new Func1<Float, Float>() { - @Override - public Float call(final Float direction) { - final IGeoData geoData = app.currentGeo(); - return fixDirection(geoData, direction); - } - }); - + private static <T> Observable<T> throttleIfNeeded(final Observable<T> observable, final long windowDuration, final TimeUnit unit) { + return windowDuration > 0 ? observable.throttleFirst(windowDuration, unit) : observable; } - private static float fixDirection(final IGeoData geoData, final float direction) { - final boolean useGPSBearing = !Settings.isUseCompass() || geoData.getSpeed() > 5; - return useGPSBearing ? DirectionProvider.reverseDirectionNow(geoData.getBearing()) : direction; + /** + * Register the current GeoDirHandler for GeoData and direction information (if the preferences allow it). + * + * @param flags a combination of UPDATE_GEODATA, UPDATE_DIRECTION, UPDATE_GEODIR, and LOW_POWER + * @return a subscription which can be used to stop the handler + */ + public Subscription start(final int flags) { + return start(flags, 0, TimeUnit.SECONDS); } /** - * Register the current GeoDirHandler for GeoData and direction information (if the - * preferences allow it). + * Register the current GeoDirHandler for GeoData and direction information (if the preferences allow it). + * + * @param flags a combination of UPDATE_GEODATA, UPDATE_DIRECTION, UPDATE_GEODIR, and LOW_POWER + * @param windowDuration if greater than 0, the size of the window duration during which no new value will be presented + * @param unit the unit for the windowDuration + * @return a subscription which can be used to stop the handler */ - public Subscription start(final int flags) { + public Subscription start(final int flags, final long windowDuration, final TimeUnit unit) { final CompositeSubscription subscriptions = new CompositeSubscription(); + final boolean lowPower = (flags & LOW_POWER) != 0; + final Sensors sensors = Sensors.getInstance(); + if ((flags & UPDATE_GEODATA) != 0) { - subscriptions.add(app.geoDataObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<IGeoData>() { + subscriptions.add(throttleIfNeeded(sensors.geoDataObservable(lowPower), windowDuration, unit).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<GeoData>() { @Override - public void call(final IGeoData geoData) { + public void call(final GeoData geoData) { updateGeoData(geoData); } })); } if ((flags & UPDATE_DIRECTION) != 0) { - subscriptions.add(fixedDirection().observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Float>() { + subscriptions.add(throttleIfNeeded(sensors.directionObservable(), windowDuration, unit).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Float>() { @Override public void call(final Float direction) { updateDirection(direction); @@ -102,14 +104,15 @@ public abstract class GeoDirHandler { })); } if ((flags & UPDATE_GEODIR) != 0) { - subscriptions.add(Observable.combineLatest(app.geoDataObservable(), app.directionObservable(), new Func2<IGeoData, Float, ImmutablePair<IGeoData, Float>>() { + // combineOnLatest() does not implement backpressure handling, so we need to explicitely use a backpressure operator there. + subscriptions.add(throttleIfNeeded(Observable.combineLatest(sensors.geoDataObservable(lowPower), sensors.directionObservable(), new Func2<GeoData, Float, ImmutablePair<GeoData, Float>>() { @Override - public ImmutablePair<IGeoData, Float> call(final IGeoData geoData, final Float direction) { - return ImmutablePair.of(geoData, fixDirection(geoData, direction)); + public ImmutablePair<GeoData, Float> call(final GeoData geoData, final Float direction) { + return ImmutablePair.of(geoData, direction); } - }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<ImmutablePair<IGeoData, Float>>() { + }), windowDuration, unit).onBackpressureDrop().observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<ImmutablePair<GeoData, Float>>() { @Override - public void call(final ImmutablePair<IGeoData, Float> geoDir) { + public void call(final ImmutablePair<GeoData, Float> geoDir) { updateGeoDir(geoDir.left, geoDir.right); } })); diff --git a/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java new file mode 100644 index 0000000..d7aa113 --- /dev/null +++ b/main/src/cgeo/geocaching/sensors/GpsStatusProvider.java @@ -0,0 +1,99 @@ +package cgeo.geocaching.sensors; + +import cgeo.geocaching.sensors.GpsStatusProvider.Status; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils.LooperCallbacks; + +import rx.Observable; + +import android.content.Context; +import android.location.GpsSatellite; +import android.location.GpsStatus; +import android.location.LocationManager; + +public class GpsStatusProvider extends LooperCallbacks<Status> { + + public static class Status { + final public boolean gpsEnabled; + final public int satellitesVisible; + final public int satellitesFixed; + + public Status(final boolean gpsEnabled, final int satellitesVisible, final int satellitesFixed) { + this.gpsEnabled = gpsEnabled; + this.satellitesVisible = satellitesVisible; + this.satellitesFixed = satellitesFixed; + } + } + + private final LocationManager geoManager; + private final GpsStatus.Listener gpsStatusListener = new GpsStatusListener(); + private Status latest = new Status(false, 0, 0); + + private static final Status NO_GPS = new Status(false, 0, 0); + + /** + * Build a new gps status provider object. + * <p/> + * There is no need to instantiate more than one such object in an application, as observers can be added + * at will. + * + * @param context the context used to retrieve the system services + */ + protected GpsStatusProvider(final Context context) { + geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + public static Observable<Status> create(final Context context) { + return Observable.create(new GpsStatusProvider(context)); + } + + @Override + protected void onStart() { + Log.d("GpsStatusProvider: starting the GPS status listener"); + subject.onNext(NO_GPS); + geoManager.addGpsStatusListener(gpsStatusListener); + } + + @Override + protected void onStop() { + Log.d("GpsStatusProvider: stopping the GPS status listener"); + geoManager.removeGpsStatusListener(gpsStatusListener); + } + + private final class GpsStatusListener implements GpsStatus.Listener { + + @Override + public void onGpsStatusChanged(final int event) { + switch (event) { + case GpsStatus.GPS_EVENT_FIRST_FIX: + case GpsStatus.GPS_EVENT_SATELLITE_STATUS: { + final GpsStatus status = geoManager.getGpsStatus(null); + int visible = 0; + int fixed = 0; + for (final GpsSatellite satellite : status.getSatellites()) { + if (satellite.usedInFix()) { + fixed++; + } + visible++; + } + if (visible == latest.satellitesVisible && fixed == latest.satellitesFixed) { + return; + } + latest = new Status(true, visible, fixed); + break; + } + case GpsStatus.GPS_EVENT_STARTED: + latest = new Status(true, 0, 0); + break; + case GpsStatus.GPS_EVENT_STOPPED: + latest = new Status(false, 0, 0); + break; + default: + throw new IllegalStateException(); + } + + subject.onNext(latest); + } + } + +} diff --git a/main/src/cgeo/geocaching/sensors/IGeoData.java b/main/src/cgeo/geocaching/sensors/IGeoData.java deleted file mode 100644 index 5b4f046..0000000 --- a/main/src/cgeo/geocaching/sensors/IGeoData.java +++ /dev/null @@ -1,22 +0,0 @@ -package cgeo.geocaching.sensors; - -import cgeo.geocaching.enumerations.LocationProviderType; -import cgeo.geocaching.geopoint.Geopoint; - -import android.location.Location; - -public interface IGeoData { - - public Location getLocation(); - public LocationProviderType getLocationProvider(); - - public boolean isPseudoLocation(); - - public Geopoint getCoords(); - public float getBearing(); - public float getSpeed(); - public float getAccuracy(); - public boolean getGpsEnabled(); - public int getSatellitesVisible(); - public int getSatellitesFixed(); -} diff --git a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java b/main/src/cgeo/geocaching/sensors/LocationProviderType.java index f2c79fe..16a50b8 100644 --- a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java +++ b/main/src/cgeo/geocaching/sensors/LocationProviderType.java @@ -1,10 +1,13 @@ -package cgeo.geocaching.enumerations; +package cgeo.geocaching.sensors; import cgeo.geocaching.R; public enum LocationProviderType { GPS(R.string.loc_gps), NETWORK(R.string.loc_net), + FUSED(R.string.loc_fused), + LOW_POWER(R.string.loc_low_power), + HOME(R.string.loc_home), LAST(R.string.loc_last); public final int resourceId; diff --git a/main/src/cgeo/geocaching/sensors/OrientationProvider.java b/main/src/cgeo/geocaching/sensors/OrientationProvider.java new file mode 100644 index 0000000..ce84ffb --- /dev/null +++ b/main/src/cgeo/geocaching/sensors/OrientationProvider.java @@ -0,0 +1,72 @@ +package cgeo.geocaching.sensors; + +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils.LooperCallbacks; + +import rx.Observable; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; + +public class OrientationProvider extends LooperCallbacks<Float> implements SensorEventListener { + + private final SensorManager sensorManager; + private final Sensor orientationSensor; + + @SuppressWarnings("deprecation") + protected OrientationProvider(final Context context) { + sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + orientationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); + if (orientationSensor != null) { + Log.d("OrientationProvider: sensor found"); + } else { + Log.w("OrientationProvider: no orientation sensor on this device"); + } + } + + @SuppressWarnings("deprecation") + public static boolean hasOrientationSensor(final Context context) { + return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_ORIENTATION) != null; + } + + @Override + public void onSensorChanged(final SensorEvent event) { + subject.onNext(event.values[0]); + } + + @Override + public void onAccuracyChanged(final Sensor sensor, final int accuracy) { + /* + * There is a bug in Android, which apparently causes this method to be called every + * time the sensor _value_ changed, even if the _accuracy_ did not change. Do not have any code in here. + * + * See for example https://code.google.com/p/android/issues/detail?id=14792 + */ + } + + @Override + public void onStart() { + if (orientationSensor != null) { + Log.d("OrientationProvider: starting the orientation provider"); + sensorManager.registerListener(this, orientationSensor, SensorManager.SENSOR_DELAY_NORMAL); + } else { + subject.onError(new RuntimeException("orientation sensor is absent on this device")); + } + } + + @Override + public void onStop() { + if (orientationSensor != null) { + Log.d("OrientationProvider: stopping the orientation provider"); + sensorManager.unregisterListener(this); + } + } + + public static Observable<Float> create(final Context context) { + return Observable.create(new OrientationProvider(context)).onBackpressureDrop(); + } + +} diff --git a/main/src/cgeo/geocaching/sensors/RotationProvider.java b/main/src/cgeo/geocaching/sensors/RotationProvider.java new file mode 100644 index 0000000..c63e39f --- /dev/null +++ b/main/src/cgeo/geocaching/sensors/RotationProvider.java @@ -0,0 +1,97 @@ +package cgeo.geocaching.sensors; + +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils.LooperCallbacks; + +import rx.Observable; + +import android.annotation.TargetApi; +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; + +public class RotationProvider extends LooperCallbacks<Float> implements SensorEventListener { + + private final SensorManager sensorManager; + private final Sensor rotationSensor; + private final float[] rotationMatrix = new float[16]; + private final float[] orientation = new float[4]; + private final float[] values = new float[4]; + + @TargetApi(19) + protected RotationProvider(final Context context, final boolean lowPower) { + sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + // The geomagnetic rotation vector introduced in Android 4.4 (API 19) requires less power. Favour it + // even if it is more sensible to noise in low-power settings. + final Sensor sensor = lowPower ? sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR) : null; + if (sensor != null) { + rotationSensor = sensor; + Log.d("RotationProvider: geomagnetic (low-power) sensor found"); + } else { + rotationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); + if (rotationSensor != null) { + Log.d("RotationProvider: sensor found"); + } else { + Log.w("RotationProvider: no rotation sensor on this device"); + } + } + } + + public static boolean hasRotationSensor(final Context context) { + return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null; + } + + @TargetApi(19) + public static boolean hasGeomagneticRotationSensor(final Context context) { + return ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR) != null; + } + + @Override + public void onSensorChanged(final SensorEvent event) { + // On some Samsung devices, SensorManager#getRotationMatrixFromVector throws an exception if the rotation + // vector has more than 4 elements. Since only the four first elements are used, we can truncate the vector + // without losing precision. + if (event.values.length > 4) { + System.arraycopy(event.values, 0, values, 0, 4); + SensorManager.getRotationMatrixFromVector(rotationMatrix, values); + } else { + SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values); + } + SensorManager.getOrientation(rotationMatrix, orientation); + subject.onNext((float) (orientation[0] * 180 / Math.PI)); + } + + @Override + public void onAccuracyChanged(final Sensor sensor, final int accuracy) { + } + + @Override + public void onStart() { + if (rotationSensor != null) { + Log.d("RotationProvider: starting the rotation provider"); + try { + sensorManager.registerListener(this, rotationSensor, SensorManager.SENSOR_DELAY_NORMAL); + } catch (final Exception e) { + Log.w("RotationProvider: unable to register listener", e); + subject.onError(e); + } + } else { + subject.onError(new RuntimeException("rotation sensor is absent on this device")); + } + } + + @Override + public void onStop() { + if (rotationSensor != null) { + Log.d("RotationProvider: stopping the rotation provider"); + sensorManager.unregisterListener(this); + } + } + + public static Observable<Float> create(final Context context, final boolean lowPower) { + return Observable.create(new RotationProvider(context, lowPower)).onBackpressureDrop(); + } + +} diff --git a/main/src/cgeo/geocaching/sensors/Sensors.java b/main/src/cgeo/geocaching/sensors/Sensors.java new file mode 100644 index 0000000..c3f6ce7 --- /dev/null +++ b/main/src/cgeo/geocaching/sensors/Sensors.java @@ -0,0 +1,165 @@ +package cgeo.geocaching.sensors; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.playservices.LocationProvider; +import cgeo.geocaching.sensors.GpsStatusProvider.Status; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.AngleUtils; +import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; + +import org.eclipse.jdt.annotation.NonNull; + +import rx.Observable; +import rx.functions.Action1; +import rx.functions.Func1; + +import android.content.Context; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class Sensors { + + private Observable<GeoData> geoDataObservable; + private Observable<GeoData> geoDataObservableLowPower; + private Observable<Float> directionObservable; + private Observable<Status> gpsStatusObservable; + @NonNull private volatile GeoData currentGeo = GeoData.DUMMY_LOCATION; + private volatile float currentDirection = 0.0f; + private volatile boolean hasValidLocation = false; + private final boolean hasCompassCapabilities; + private final CgeoApplication app = CgeoApplication.getInstance(); + + private static class InstanceHolder { + static final Sensors INSTANCE = new Sensors(); + } + + private final Action1<GeoData> rememberGeodataAction = new Action1<GeoData>() { + @Override + public void call(final GeoData geoData) { + currentGeo = geoData; + hasValidLocation = true; + } + }; + + private final Action1<Float> onNextrememberDirectionAction = new Action1<Float>() { + @Override + public void call(final Float direction) { + currentDirection = direction; + } + }; + + private Sensors() { + gpsStatusObservable = GpsStatusProvider.create(app).replay(1).refCount(); + final Context context = CgeoApplication.getInstance().getApplicationContext(); + hasCompassCapabilities = RotationProvider.hasRotationSensor(context) || OrientationProvider.hasOrientationSensor(context); + } + + public static final Sensors getInstance() { + return InstanceHolder.INSTANCE; + } + + private final Func1<Throwable, Observable<GeoData>> fallbackToGeodataProvider = new Func1<Throwable, Observable<GeoData>>() { + @Override + public Observable<GeoData> call(final Throwable throwable) { + Log.e("Cannot use Play Services location provider, falling back to GeoDataProvider", throwable); + Settings.setUseGooglePlayServices(false); + return GeoDataProvider.create(app); + } + }; + + public void setupGeoDataObservables(final boolean useGooglePlayServices, final boolean useLowPowerLocation) { + if (useGooglePlayServices) { + geoDataObservable = LocationProvider.getMostPrecise(app).onErrorResumeNext(fallbackToGeodataProvider).doOnNext(rememberGeodataAction); + if (useLowPowerLocation) { + geoDataObservableLowPower = LocationProvider.getLowPower(app).doOnNext(rememberGeodataAction).onErrorResumeNext(geoDataObservable); + } else { + geoDataObservableLowPower = geoDataObservable; + } + } else { + geoDataObservable = RxUtils.rememberLast(GeoDataProvider.create(app).doOnNext(rememberGeodataAction), null); + geoDataObservableLowPower = geoDataObservable; + } + } + + private static final Func1<GeoData, Float> GPS_TO_DIRECTION = new Func1<GeoData, Float>() { + @Override + public Float call(final GeoData geoData) { + return AngleUtils.reverseDirectionNow(geoData.getBearing()); + } + }; + + public void setupDirectionObservable(final boolean useLowPower) { + // If we have no magnetic sensor, there is no point in trying to setup any, we will always get the direction from the GPS. + if (!hasCompassCapabilities) { + Log.i("No compass capabilities, using only the GPS for the orientation"); + directionObservable = RxUtils.rememberLast(geoDataObservableLowPower.map(GPS_TO_DIRECTION).doOnNext(onNextrememberDirectionAction), 0f); + return; + } + + // Combine the magnetic direction observable with the GPS when compass is disabled or speed is high enough. + final AtomicBoolean useDirectionFromGps = new AtomicBoolean(false); + + // The rotation sensor seems to be bogus on some devices. We should start with the orientation one, except when we explicitely + // want to use the low-power geomagnetic rotation sensor or when we do not have an orientation sensor. + final boolean useRotationSensor = (useLowPower && RotationProvider.hasGeomagneticRotationSensor(app)) || !OrientationProvider.hasOrientationSensor(app); + final Observable<Float> sensorDirectionObservable = useRotationSensor ? RotationProvider.create(app, useLowPower) : OrientationProvider.create(app); + final Observable<Float> magneticDirectionObservable = sensorDirectionObservable.onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() { + @Override + public Observable<? extends Float> call(final Throwable throwable) { + Log.e("Device orientation is not available due to sensors error, disabling compass", throwable); + Settings.setUseCompass(false); + return Observable.<Float>never().startWith(0.0f); + } + }).filter(new Func1<Float, Boolean>() { + @Override + public Boolean call(final Float aFloat) { + return Settings.isUseCompass() && !useDirectionFromGps.get(); + } + }); + + final Observable<Float> directionFromGpsObservable = geoDataObservableLowPower.filter(new Func1<GeoData, Boolean>() { + @Override + public Boolean call(final GeoData geoData) { + final boolean useGps = geoData.getSpeed() > 5.0f; + useDirectionFromGps.set(useGps); + return useGps || !Settings.isUseCompass(); + } + }).map(GPS_TO_DIRECTION); + + directionObservable = RxUtils.rememberLast(Observable.merge(magneticDirectionObservable, directionFromGpsObservable).doOnNext(onNextrememberDirectionAction), 0f); + } + + public Observable<GeoData> geoDataObservable(final boolean lowPower) { + return lowPower ? geoDataObservableLowPower : geoDataObservable; + } + + public Observable<Float> directionObservable() { + return directionObservable; + } + + public Observable<Status> gpsStatusObservable() { + if (gpsStatusObservable == null) { + gpsStatusObservable = GpsStatusProvider.create(app).share(); + } + return gpsStatusObservable; + } + + @NonNull + public GeoData currentGeo() { + return currentGeo; + } + + public boolean hasValidLocation() { + return hasValidLocation; + } + + public float currentDirection() { + return currentDirection; + } + + public boolean hasCompassCapabilities() { + return hasCompassCapabilities; + } + +} diff --git a/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java b/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java index 1930c17..aeeef9f 100644 --- a/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java +++ b/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java @@ -13,25 +13,25 @@ import android.util.AttributeSet; */ public abstract class AbstractAttributeBasedPrefence extends Preference { - public AbstractAttributeBasedPrefence(Context context) { + public AbstractAttributeBasedPrefence(final Context context) { super(context); } - public AbstractAttributeBasedPrefence(Context context, AttributeSet attrs) { + public AbstractAttributeBasedPrefence(final Context context, final AttributeSet attrs) { super(context, attrs); processAttributes(context, attrs, 0); } - public AbstractAttributeBasedPrefence(Context context, AttributeSet attrs, int defStyle) { + public AbstractAttributeBasedPrefence(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); processAttributes(context, attrs, defStyle); } - private void processAttributes(Context context, @Nullable AttributeSet attrs, int defStyle) { + private void processAttributes(final Context context, @Nullable final AttributeSet attrs, final int defStyle) { if (attrs == null) { return; } - TypedArray types = context.obtainStyledAttributes(attrs, getAttributeNames(), + final TypedArray types = context.obtainStyledAttributes(attrs, getAttributeNames(), defStyle, 0); processAttributeValues(types); @@ -42,7 +42,6 @@ public abstract class AbstractAttributeBasedPrefence extends Preference { /** * Evaluate the attributes which where requested in {@link AbstractAttributeBasedPrefence#getAttributeNames()}. * - * @param values */ protected abstract void processAttributeValues(TypedArray values); diff --git a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java index 2f83028..7978d76 100644 --- a/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/AbstractCheckCredentialsPreference.java @@ -11,10 +11,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; -import rx.util.async.Async; import android.app.ProgressDialog; import android.content.Context; @@ -25,11 +24,11 @@ import android.util.AttributeSet; public abstract class AbstractCheckCredentialsPreference extends AbstractClickablePreference { - public AbstractCheckCredentialsPreference(Context context, AttributeSet attrs) { + public AbstractCheckCredentialsPreference(final Context context, final AttributeSet attrs) { super(context, attrs); } - public AbstractCheckCredentialsPreference(Context context, AttributeSet attrs, int defStyle) { + public AbstractCheckCredentialsPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @@ -57,7 +56,7 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab } @Override - public boolean onPreferenceClick(Preference preference) { + public boolean onPreferenceClick(final Preference preference) { final Resources res = settingsActivity.getResources(); final ImmutablePair<String, String> credentials = getCredentials(); @@ -74,10 +73,10 @@ public abstract class AbstractCheckCredentialsPreference extends AbstractClickab loginDialog.setCancelable(false); Cookies.clearCookies(); - AndroidObservable.bindActivity(settingsActivity, Async.start(new Func0<ImmutablePair<StatusCode, Observable<Drawable>>>() { + AppObservable.bindActivity(settingsActivity, Observable.defer(new Func0<Observable<ImmutablePair<StatusCode, Observable<Drawable>>>>() { @Override - public ImmutablePair<StatusCode, Observable<Drawable>> call() { - return login(); + public Observable<ImmutablePair<StatusCode, Observable<Drawable>>> call() { + return Observable.just(login()); } })).subscribeOn(RxUtils.networkScheduler).subscribe(new Action1<ImmutablePair<StatusCode, Observable<Drawable>>>() { @Override diff --git a/main/src/cgeo/geocaching/settings/AbstractClickablePreference.java b/main/src/cgeo/geocaching/settings/AbstractClickablePreference.java index f4080cd..57fdf36 100644 --- a/main/src/cgeo/geocaching/settings/AbstractClickablePreference.java +++ b/main/src/cgeo/geocaching/settings/AbstractClickablePreference.java @@ -10,18 +10,18 @@ abstract class AbstractClickablePreference extends Preference { final SettingsActivity activity; - public AbstractClickablePreference(Context context, AttributeSet attrs) { + public AbstractClickablePreference(final Context context, final AttributeSet attrs) { super(context, attrs); activity = (SettingsActivity) context; } - public AbstractClickablePreference(Context context, AttributeSet attrs, int defStyle) { + public AbstractClickablePreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); activity = (SettingsActivity) context; } @Override - protected View onCreateView(ViewGroup parent) { + protected View onCreateView(final ViewGroup parent) { setOnPreferenceClickListener(getOnPreferenceClickListener(activity)); return super.onCreateView(parent); } diff --git a/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java b/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java index 7091f01..afb0b7f 100644 --- a/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java +++ b/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java @@ -23,20 +23,20 @@ public class CapabilitiesPreference extends AbstractAttributeBasedPrefence { private String connectorCode; - public CapabilitiesPreference(Context context) { + public CapabilitiesPreference(final Context context) { super(context); } - public CapabilitiesPreference(Context context, AttributeSet attrs) { + public CapabilitiesPreference(final Context context, final AttributeSet attrs) { super(context, attrs); } - public CapabilitiesPreference(Context context, AttributeSet attrs, int defStyle) { + public CapabilitiesPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override - public View getView(View convertView, ViewGroup parent) { + public View getView(final View convertView, final ViewGroup parent) { setOnPreferenceClickListener(new ClickListener()); return super.getView(convertView, parent); } @@ -44,15 +44,15 @@ public class CapabilitiesPreference extends AbstractAttributeBasedPrefence { private final class ClickListener implements OnPreferenceClickListener { @Override public boolean onPreferenceClick(final Preference preference) { - WebView htmlView = new WebView(preference.getContext()); + final WebView htmlView = new WebView(preference.getContext()); htmlView.loadDataWithBaseURL(null, createCapabilitiesMessage(), "text/html", "utf-8", null); - AlertDialog.Builder builder = new AlertDialog.Builder(preference.getContext()); + final AlertDialog.Builder builder = new AlertDialog.Builder(preference.getContext()); builder.setView(htmlView) .setIcon(android.R.drawable.ic_dialog_info) .setTitle(R.string.settings_features) .setPositiveButton(R.string.err_none, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int id) { + public void onClick(final DialogInterface dialog, final int id) { dialog.cancel(); } }); @@ -63,11 +63,11 @@ public class CapabilitiesPreference extends AbstractAttributeBasedPrefence { public String createCapabilitiesMessage() { // TODO: this needs a better key for the connectors - IConnector connector = ConnectorFactory.getConnector(connectorCode + "1234"); - StringBuilder builder = new StringBuilder("<p>" + final IConnector connector = ConnectorFactory.getConnector(connectorCode + "1234"); + final StringBuilder builder = new StringBuilder("<p>" + TextUtils.htmlEncode(CgeoApplication.getInstance().getString(R.string.feature_description)) + "</p><ul>"); - for (String capability : connector.getCapabilities()) { + for (final String capability : connector.getCapabilities()) { builder.append("<li>").append(TextUtils.htmlEncode(capability)).append("</li>"); } @@ -76,7 +76,7 @@ public class CapabilitiesPreference extends AbstractAttributeBasedPrefence { } @Override - protected void processAttributeValues(TypedArray values) { + protected void processAttributeValues(final TypedArray values) { connectorCode = values.getString(0); } diff --git a/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java b/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java index 35df787..00b46cc 100644 --- a/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java +++ b/main/src/cgeo/geocaching/settings/CheckBoxWithPopupPreference.java @@ -20,26 +20,26 @@ public class CheckBoxWithPopupPreference extends CheckBoxPreference { private String urlButton; private OnPreferenceChangeListener baseOnPrefChangeListener = null; - public CheckBoxWithPopupPreference(Context context) { + public CheckBoxWithPopupPreference(final Context context) { super(context); } - public CheckBoxWithPopupPreference(Context context, AttributeSet attrs) { + public CheckBoxWithPopupPreference(final Context context, final AttributeSet attrs) { super(context, attrs); processAttributes(context, attrs, 0); } - public CheckBoxWithPopupPreference(Context context, AttributeSet attrs, int defStyle) { + public CheckBoxWithPopupPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); processAttributes(context, attrs, defStyle); } - private void processAttributes(Context context, AttributeSet attrs, int defStyle) { + private void processAttributes(final Context context, final AttributeSet attrs, final int defStyle) { if (attrs == null) { return; // coward's retreat } - TypedArray types = context.obtainStyledAttributes(attrs, new int[] { + final TypedArray types = context.obtainStyledAttributes(attrs, new int[] { R.attr.title, R.attr.text, R.attr.url, R.attr.urlButton }, defStyle, 0); @@ -52,7 +52,7 @@ public class CheckBoxWithPopupPreference extends CheckBoxPreference { } @Override - protected View onCreateView(ViewGroup parent) { + protected View onCreateView(final ViewGroup parent) { if (baseOnPrefChangeListener == null) { baseOnPrefChangeListener = getOnPreferenceChangeListener(); @@ -61,7 +61,7 @@ public class CheckBoxWithPopupPreference extends CheckBoxPreference { // show dialog when checkbox enabled setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override - public boolean onPreferenceChange(final Preference preference, Object newValue) { + public boolean onPreferenceChange(final Preference preference, final Object newValue) { if (baseOnPrefChangeListener != null) { baseOnPrefChangeListener.onPreferenceChange(preference, newValue); } diff --git a/main/src/cgeo/geocaching/settings/CheckECCredentialsPreference.java b/main/src/cgeo/geocaching/settings/CheckECCredentialsPreference.java index f5d9ab5..8f7da2c 100644 --- a/main/src/cgeo/geocaching/settings/CheckECCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/CheckECCredentialsPreference.java @@ -14,11 +14,11 @@ import android.util.AttributeSet; public class CheckECCredentialsPreference extends AbstractCheckCredentialsPreference { - public CheckECCredentialsPreference(Context context, AttributeSet attrs) { + public CheckECCredentialsPreference(final Context context, final AttributeSet attrs) { super(context, attrs); } - public CheckECCredentialsPreference(Context context, AttributeSet attrs, int defStyle) { + public CheckECCredentialsPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } diff --git a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java index 0269f3b..04f406f 100644 --- a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java @@ -13,11 +13,11 @@ import android.util.AttributeSet; public class CheckGcCredentialsPreference extends AbstractCheckCredentialsPreference { - public CheckGcCredentialsPreference(Context context, AttributeSet attrs) { + public CheckGcCredentialsPreference(final Context context, final AttributeSet attrs) { super(context, attrs); } - public CheckGcCredentialsPreference(Context context, AttributeSet attrs, int defStyle) { + public CheckGcCredentialsPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @@ -31,8 +31,7 @@ public class CheckGcCredentialsPreference extends AbstractCheckCredentialsPrefer final StatusCode loginResult = GCLogin.getInstance().login(); switch (loginResult) { case NO_ERROR: - GCLogin.detectGcCustomDate(); - return ImmutablePair.of(StatusCode.NO_ERROR, GCLogin.getInstance().downloadAvatarAndGetMemberStatus()); + return ImmutablePair.of(StatusCode.NO_ERROR, GCLogin.getInstance().downloadAvatar()); default: return ImmutablePair.of(loginResult, null); } diff --git a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java index af07041..267a0b3 100644 --- a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java +++ b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java @@ -14,20 +14,20 @@ import android.util.AttributeSet; */ public class EditPasswordPreference extends EditTextPreference { - public EditPasswordPreference(Context context) { + public EditPasswordPreference(final Context context) { super(context); } - public EditPasswordPreference(Context context, AttributeSet attrs) { + public EditPasswordPreference(final Context context, final AttributeSet attrs) { super(context, attrs); } - public EditPasswordPreference(Context context, AttributeSet attrs, int defStyle) { + public EditPasswordPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override - public void setSummary(CharSequence summary) { + public void setSummary(final CharSequence summary) { if (StringUtils.isBlank(summary)) { super.setSummary(StringUtils.EMPTY); } else { diff --git a/main/src/cgeo/geocaching/settings/InfoPreference.java b/main/src/cgeo/geocaching/settings/InfoPreference.java index 8040a62..d1ece92 100644 --- a/main/src/cgeo/geocaching/settings/InfoPreference.java +++ b/main/src/cgeo/geocaching/settings/InfoPreference.java @@ -39,22 +39,22 @@ public class InfoPreference extends AbstractAttributeBasedPrefence { private LayoutInflater inflater; - public InfoPreference(Context context) { + public InfoPreference(final Context context) { super(context); init(context); } - public InfoPreference(Context context, AttributeSet attrs) { + public InfoPreference(final Context context, final AttributeSet attrs) { super(context, attrs); init(context); } - public InfoPreference(Context context, AttributeSet attrs, int defStyle) { + public InfoPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); init(context); } - private void init(Context context) { + private void init(final Context context) { inflater = ((Activity) context).getLayoutInflater(); setPersistent(false); } @@ -65,14 +65,14 @@ public class InfoPreference extends AbstractAttributeBasedPrefence { } @Override - protected void processAttributeValues(TypedArray values) { + protected void processAttributeValues(final TypedArray values) { text = values.getString(0); url = values.getString(1); urlButton = values.getString(2); } @Override - protected View onCreateView(ViewGroup parent) { + protected View onCreateView(final ViewGroup parent) { // show popup when clicked setOnPreferenceClickListener(new OnPreferenceClickListener() { @@ -91,14 +91,12 @@ public class InfoPreference extends AbstractAttributeBasedPrefence { /** * Add an info icon at the left hand side of the preference. * - * @param parent - * @return */ - private View addInfoIcon(ViewGroup parent) { - View preferenceView = super.onCreateView(parent); + private View addInfoIcon(final ViewGroup parent) { + final View preferenceView = super.onCreateView(parent); - ImageView iconView = (ImageView) inflater.inflate(R.layout.preference_info_icon, parent, false); - LinearLayout frame = (LinearLayout) preferenceView.findViewById(android.R.id.widget_frame); + final ImageView iconView = (ImageView) inflater.inflate(R.layout.preference_info_icon, parent, false); + final LinearLayout frame = (LinearLayout) preferenceView.findViewById(android.R.id.widget_frame); frame.setVisibility(View.VISIBLE); frame.addView(iconView); diff --git a/main/src/cgeo/geocaching/settings/OAuthPreference.java b/main/src/cgeo/geocaching/settings/OAuthPreference.java index 54bad6d..23f3a12 100644 --- a/main/src/cgeo/geocaching/settings/OAuthPreference.java +++ b/main/src/cgeo/geocaching/settings/OAuthPreference.java @@ -2,9 +2,9 @@ package cgeo.geocaching.settings; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; +import cgeo.geocaching.activity.OAuthAuthorizationActivity.OAuthParameters; import cgeo.geocaching.connector.oc.OCAuthParams; import cgeo.geocaching.connector.oc.OCAuthorizationActivity; -import cgeo.geocaching.network.OAuthAuthorizationActivity.OAuthParameters; import cgeo.geocaching.twitter.TwitterAuthorizationActivity; import android.content.Context; diff --git a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java index 84c343a..da20039 100644 --- a/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java +++ b/main/src/cgeo/geocaching/settings/RegisterSend2CgeoPreference.java @@ -13,7 +13,7 @@ import ch.boye.httpclientandroidlib.HttpResponse; import org.apache.commons.lang3.StringUtils; import rx.Observable; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action1; import rx.functions.Func0; @@ -24,11 +24,11 @@ import android.util.AttributeSet; public class RegisterSend2CgeoPreference extends AbstractClickablePreference { - public RegisterSend2CgeoPreference(Context context, AttributeSet attrs) { + public RegisterSend2CgeoPreference(final Context context, final AttributeSet attrs) { super(context, attrs); } - public RegisterSend2CgeoPreference(Context context, AttributeSet attrs, int defStyle) { + public RegisterSend2CgeoPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @@ -36,7 +36,7 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference { protected OnPreferenceClickListener getOnPreferenceClickListener(final SettingsActivity activity) { return new OnPreferenceClickListener() { @Override - public boolean onPreferenceClick(Preference preference) { + public boolean onPreferenceClick(final Preference preference) { // satisfy static code analysis if (activity == null) { return true; @@ -55,23 +55,25 @@ public class RegisterSend2CgeoPreference extends AbstractClickablePreference { activity.getString(R.string.init_sendToCgeo_registering), true); progressDialog.setCancelable(false); - AndroidObservable.bindActivity(activity, Observable.defer(new Func0<Observable<Integer>>() { + AppObservable.bindActivity(activity, Observable.defer(new Func0<Observable<Integer>>() { @Override public Observable<Integer> call() { final String nam = StringUtils.defaultString(deviceName); final String cod = StringUtils.defaultString(deviceCode); final Parameters params = new Parameters("name", nam, "code", cod); - HttpResponse response = Network.getRequest("http://send2.cgeo.org/auth.html", params); + final HttpResponse response = Network.getRequest("http://send2.cgeo.org/auth.html", params); if (response != null && response.getStatusLine().getStatusCode() == 200) { //response was OK final String[] strings = StringUtils.split(Network.getResponseData(response), ','); - Settings.setWebNameCode(nam, strings[0]); - try { - return Observable.from(Integer.parseInt(strings[1].trim())); - } catch (final Exception e) { - Log.e("RegisterSend2CgeoPreference", e); + if (strings != null) { + Settings.setWebNameCode(nam, strings[0]); + try { + return Observable.just(Integer.parseInt(strings[1].trim())); + } catch (final Exception e) { + Log.e("RegisterSend2CgeoPreference", e); + } } } diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index d93f83f..c15bc1b 100644 --- a/main/src/cgeo/geocaching/settings/Settings.java +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -6,12 +6,11 @@ import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; import cgeo.geocaching.connector.capability.ICredentials; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCConstants; -import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.maps.CGeoMap.MapMode; import cgeo.geocaching.maps.MapProviderFactory; //import cgeo.geocaching.maps.google.v1.GoogleMapProvider; import cgeo.geocaching.maps.interfaces.GeoPointImpl; @@ -35,6 +34,8 @@ import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Environment; import android.preference.PreferenceManager; @@ -49,6 +50,10 @@ import java.util.Locale; */ public class Settings { + /** + * On opening a map, we limit the _initial_ zoom. The user can still zoom out afterwards. + */ + private static final int INITIAL_MAP_ZOOM_LIMIT = 16; private static final char HISTORY_SEPARATOR = ','; public static final int SHOW_WP_THRESHOLD_DEFAULT = 10; public static final int SHOW_WP_THRESHOLD_MAX = 50; @@ -66,11 +71,11 @@ public class Settings { StringUtils.equals(Build.MODEL, "ST25i") || // Sony Xperia U StringUtils.equals(Build.MODEL, "bq Aquaris 5"); // bq Aquaris 5 - private final static int unitsMetric = 1; - // twitter api keys - private final static @NonNull String keyConsumerPublic = CryptUtils.rot13("ESnsCvAv3kEupF1GCR3jGj"); - private final static @NonNull String keyConsumerSecret = CryptUtils.rot13("7vQWceACV9umEjJucmlpFe9FCMZSeqIqfkQ2BnhV9x"); + private final static @NonNull String TWITTER_KEY_CONSUMER_PUBLIC = CryptUtils.rot13("ESnsCvAv3kEupF1GCR3jGj"); + private final static @NonNull String TWITTER_KEY_CONSUMER_SECRET = CryptUtils.rot13("7vQWceACV9umEjJucmlpFe9FCMZSeqIqfkQ2BnhV9x"); + + private static boolean useCompass = true; public enum CoordInputFormatEnum { Plain, @@ -78,7 +83,7 @@ public class Settings { Min, Sec; - static int DEFAULT_INT_VALUE = Min.ordinal(); + static final int DEFAULT_INT_VALUE = Min.ordinal(); public static CoordInputFormatEnum fromInt(final int id) { final CoordInputFormatEnum[] values = CoordInputFormatEnum.values(); @@ -109,13 +114,29 @@ public class Settings { } private static void migrateSettings() { - // migrate from non standard file location and integer based boolean types - final int oldVersion = getInt(R.string.pref_settingsversion, 0); - if (oldVersion < 1) { - final String oldPreferencesName = "cgeo.pref"; - final SharedPreferences old = CgeoApplication.getInstance().getSharedPreferences(oldPreferencesName, Context.MODE_PRIVATE); + final int LATEST_PREFERENCES_VERSION = 2; + final int currentVersion = getInt(R.string.pref_settingsversion, 0); + + // No need to migrate if we are up to date. + if (currentVersion == LATEST_PREFERENCES_VERSION) { + return; + } + + // No need to migrate if we don't have older settings, defaults will be used instead. + final String preferencesNameV0 = "cgeo.pref"; + final SharedPreferences prefsV0 = CgeoApplication.getInstance().getSharedPreferences(preferencesNameV0, Context.MODE_PRIVATE); + if (currentVersion == 0 && prefsV0.getAll().isEmpty()) { + final Editor e = sharedPrefs.edit(); + e.putInt(getKey(R.string.pref_settingsversion), LATEST_PREFERENCES_VERSION); + e.apply(); + return; + } + + if (currentVersion < 1) { + // migrate from non standard file location and integer based boolean types final Editor e = sharedPrefs.edit(); +<<<<<<< HEAD e.putString(getKey(R.string.pref_temp_twitter_token_secret), old.getString(getKey(R.string.pref_temp_twitter_token_secret), null)); e.putString(getKey(R.string.pref_temp_twitter_token_public), old.getString(getKey(R.string.pref_temp_twitter_token_public), null)); e.putBoolean(getKey(R.string.pref_help_shown), old.getInt(getKey(R.string.pref_help_shown), 0) != 0); @@ -171,16 +192,72 @@ public class Settings { e.putBoolean(getKey(R.string.pref_debug), old.getBoolean(getKey(R.string.pref_debug), false)); e.putBoolean(getKey(R.string.pref_hidelivemaphint), old.getInt(getKey(R.string.pref_hidelivemaphint), 0) != 0); e.putInt(getKey(R.string.pref_livemaphintshowcount), old.getInt(getKey(R.string.pref_livemaphintshowcount), 0)); +======= + e.putString(getKey(R.string.pref_temp_twitter_token_secret), prefsV0.getString(getKey(R.string.pref_temp_twitter_token_secret), null)); + e.putString(getKey(R.string.pref_temp_twitter_token_public), prefsV0.getString(getKey(R.string.pref_temp_twitter_token_public), null)); + e.putBoolean(getKey(R.string.pref_help_shown), prefsV0.getInt(getKey(R.string.pref_help_shown), 0) != 0); + e.putFloat(getKey(R.string.pref_anylongitude), prefsV0.getFloat(getKey(R.string.pref_anylongitude), 0)); + e.putFloat(getKey(R.string.pref_anylatitude), prefsV0.getFloat(getKey(R.string.pref_anylatitude), 0)); + e.putBoolean(getKey(R.string.pref_offlinemaps), 0 != prefsV0.getInt(getKey(R.string.pref_offlinemaps), 1)); + e.putBoolean(getKey(R.string.pref_offlinewpmaps), 0 != prefsV0.getInt(getKey(R.string.pref_offlinewpmaps), 0)); + e.putString(getKey(R.string.pref_webDeviceCode), prefsV0.getString(getKey(R.string.pref_webDeviceCode), null)); + e.putString(getKey(R.string.pref_webDeviceName), prefsV0.getString(getKey(R.string.pref_webDeviceName), null)); + e.putBoolean(getKey(R.string.pref_maplive), prefsV0.getInt(getKey(R.string.pref_maplive), 1) != 0); + e.putInt(getKey(R.string.pref_mapsource), prefsV0.getInt(getKey(R.string.pref_mapsource), MAP_SOURCE_DEFAULT)); + e.putBoolean(getKey(R.string.pref_twitter), 0 != prefsV0.getInt(getKey(R.string.pref_twitter), 0)); + e.putBoolean(getKey(R.string.pref_showaddress), 0 != prefsV0.getInt(getKey(R.string.pref_showaddress), 1)); + e.putBoolean(getKey(R.string.pref_showcaptcha), prefsV0.getBoolean(getKey(R.string.pref_showcaptcha), false)); + e.putBoolean(getKey(R.string.pref_maptrail), prefsV0.getInt(getKey(R.string.pref_maptrail), 1) != 0); + e.putInt(getKey(R.string.pref_lastmapzoom), prefsV0.getInt(getKey(R.string.pref_lastmapzoom), 14)); + e.putBoolean(getKey(R.string.pref_livelist), 0 != prefsV0.getInt(getKey(R.string.pref_livelist), 1)); + e.putBoolean(getKey(R.string.pref_units_imperial), prefsV0.getInt(getKey(R.string.pref_units_imperial), 1) != 1); + e.putBoolean(getKey(R.string.pref_skin), prefsV0.getInt(getKey(R.string.pref_skin), 0) != 0); + e.putInt(getKey(R.string.pref_lastusedlist), prefsV0.getInt(getKey(R.string.pref_lastusedlist), StoredList.STANDARD_LIST_ID)); + e.putString(getKey(R.string.pref_cachetype), prefsV0.getString(getKey(R.string.pref_cachetype), CacheType.ALL.id)); + e.putString(getKey(R.string.pref_twitter_token_secret), prefsV0.getString(getKey(R.string.pref_twitter_token_secret), null)); + e.putString(getKey(R.string.pref_twitter_token_public), prefsV0.getString(getKey(R.string.pref_twitter_token_public), null)); + e.putInt(getKey(R.string.pref_version), prefsV0.getInt(getKey(R.string.pref_version), 0)); + e.putBoolean(getKey(R.string.pref_autoloaddesc), 0 != prefsV0.getInt(getKey(R.string.pref_autoloaddesc), 1)); + e.putBoolean(getKey(R.string.pref_ratingwanted), prefsV0.getBoolean(getKey(R.string.pref_ratingwanted), true)); + e.putBoolean(getKey(R.string.pref_friendlogswanted), prefsV0.getBoolean(getKey(R.string.pref_friendlogswanted), true)); + e.putBoolean(getKey(R.string.pref_useenglish), prefsV0.getBoolean(getKey(R.string.pref_useenglish), false)); + e.putBoolean(getKey(R.string.pref_usecompass), 0 != prefsV0.getInt(getKey(R.string.pref_usecompass), 1)); + e.putBoolean(getKey(R.string.pref_trackautovisit), prefsV0.getBoolean(getKey(R.string.pref_trackautovisit), false)); + e.putBoolean(getKey(R.string.pref_sigautoinsert), prefsV0.getBoolean(getKey(R.string.pref_sigautoinsert), false)); + e.putBoolean(getKey(R.string.pref_logimages), prefsV0.getBoolean(getKey(R.string.pref_logimages), false)); + e.putBoolean(getKey(R.string.pref_excludedisabled), 0 != prefsV0.getInt(getKey(R.string.pref_excludedisabled), 0)); + e.putBoolean(getKey(R.string.pref_excludemine), 0 != prefsV0.getInt(getKey(R.string.pref_excludemine), 0)); + e.putString(getKey(R.string.pref_mapfile), prefsV0.getString(getKey(R.string.pref_mapfile), null)); + e.putString(getKey(R.string.pref_signature), prefsV0.getString(getKey(R.string.pref_signature), null)); + e.putString(getKey(R.string.pref_pass_vote), prefsV0.getString(getKey(R.string.pref_pass_vote), null)); + e.putString(getKey(R.string.pref_password), prefsV0.getString(getKey(R.string.pref_password), null)); + e.putString(getKey(R.string.pref_username), prefsV0.getString(getKey(R.string.pref_username), null)); + e.putString(getKey(R.string.pref_memberstatus), prefsV0.getString(getKey(R.string.pref_memberstatus), "")); + e.putInt(getKey(R.string.pref_coordinputformat), prefsV0.getInt(getKey(R.string.pref_coordinputformat), CoordInputFormatEnum.DEFAULT_INT_VALUE)); + e.putBoolean(getKey(R.string.pref_log_offline), prefsV0.getBoolean(getKey(R.string.pref_log_offline), false)); + e.putBoolean(getKey(R.string.pref_choose_list), prefsV0.getBoolean(getKey(R.string.pref_choose_list), true)); + e.putBoolean(getKey(R.string.pref_loaddirectionimg), prefsV0.getBoolean(getKey(R.string.pref_loaddirectionimg), true)); + e.putString(getKey(R.string.pref_gccustomdate), prefsV0.getString(getKey(R.string.pref_gccustomdate), GCConstants.DEFAULT_GC_DATE)); + e.putInt(getKey(R.string.pref_showwaypointsthreshold), prefsV0.getInt(getKey(R.string.pref_showwaypointsthreshold), SHOW_WP_THRESHOLD_DEFAULT)); + e.putString(getKey(R.string.pref_cookiestore), prefsV0.getString(getKey(R.string.pref_cookiestore), null)); + e.putBoolean(getKey(R.string.pref_opendetailslastpage), prefsV0.getBoolean(getKey(R.string.pref_opendetailslastpage), false)); + e.putInt(getKey(R.string.pref_lastdetailspage), prefsV0.getInt(getKey(R.string.pref_lastdetailspage), 1)); + e.putInt(getKey(R.string.pref_defaultNavigationTool), prefsV0.getInt(getKey(R.string.pref_defaultNavigationTool), NavigationAppsEnum.COMPASS.id)); + e.putInt(getKey(R.string.pref_defaultNavigationTool2), prefsV0.getInt(getKey(R.string.pref_defaultNavigationTool2), NavigationAppsEnum.INTERNAL_MAP.id)); + e.putInt(getKey(R.string.pref_livemapstrategy), prefsV0.getInt(getKey(R.string.pref_livemapstrategy), LivemapStrategy.AUTO.id)); + e.putBoolean(getKey(R.string.pref_debug), prefsV0.getBoolean(getKey(R.string.pref_debug), false)); + e.putInt(getKey(R.string.pref_livemaphintshowcount), prefsV0.getInt(getKey(R.string.pref_livemaphintshowcount), 0)); +>>>>>>> 59b8b2e26a7fff6072c4d5d96f51035dc900e0bc e.putInt(getKey(R.string.pref_settingsversion), 1); // mark migrated - e.commit(); + e.apply(); } // changes for new settings dialog - if (oldVersion < 2) { + if (currentVersion < 2) { final Editor e = sharedPrefs.edit(); - e.putBoolean(getKey(R.string.pref_units), !isUseImperialUnits()); + e.putBoolean(getKey(R.string.pref_units_imperial), useImperialUnits()); // show waypoints threshold now as a slider int wpThreshold = getWayPointsThreshold(); @@ -209,7 +286,7 @@ public class Settings { e.putString(getKey(R.string.pref_gpxExportDir), getGpxExportDir()); e.putInt(getKey(R.string.pref_settingsversion), 2); // mark migrated - e.commit(); + e.apply(); } } @@ -237,40 +314,40 @@ public class Settings { return sharedPrefs.getFloat(getKey(prefKeyId), defaultValue); } - protected static boolean putString(final int prefKeyId, final String value) { + protected static void putString(final int prefKeyId, final String value) { final SharedPreferences.Editor edit = sharedPrefs.edit(); edit.putString(getKey(prefKeyId), value); - return edit.commit(); + edit.apply(); } - protected static boolean putBoolean(final int prefKeyId, final boolean value) { + protected static void putBoolean(final int prefKeyId, final boolean value) { final SharedPreferences.Editor edit = sharedPrefs.edit(); edit.putBoolean(getKey(prefKeyId), value); - return edit.commit(); + edit.apply(); } - private static boolean putInt(final int prefKeyId, final int value) { + private static void putInt(final int prefKeyId, final int value) { final SharedPreferences.Editor edit = sharedPrefs.edit(); edit.putInt(getKey(prefKeyId), value); - return edit.commit(); + edit.apply(); } - private static boolean putLong(final int prefKeyId, final long value) { + private static void putLong(final int prefKeyId, final long value) { final SharedPreferences.Editor edit = sharedPrefs.edit(); edit.putLong(getKey(prefKeyId), value); - return edit.commit(); + edit.apply(); } - private static boolean putFloat(final int prefKeyId, final float value) { + private static void putFloat(final int prefKeyId, final float value) { final SharedPreferences.Editor edit = sharedPrefs.edit(); edit.putFloat(getKey(prefKeyId), value); - return edit.commit(); + edit.apply(); } - private static boolean remove(final int prefKeyId) { + private static void remove(final int prefKeyId) { final SharedPreferences.Editor edit = sharedPrefs.edit(); edit.remove(getKey(prefKeyId)); - return edit.commit(); + edit.apply(); } private static boolean contains(final int prefKeyId) { @@ -317,7 +394,7 @@ public class Settings { } public static String getUsername() { - return getString(R.string.pref_username, null); + return getString(R.string.pref_username, StringUtils.EMPTY); } public static boolean isGCConnectorActive() { @@ -333,19 +410,20 @@ public class Settings { } public static boolean isGCPremiumMember() { - // Basic Member, Premium Member, ??? - return GCConstants.MEMBER_STATUS_PM.equalsIgnoreCase(Settings.getGCMemberStatus()); + final String memberStatus = Settings.getGCMemberStatus(); + return StringUtils.equalsIgnoreCase(memberStatus, GCConstants.MEMBER_STATUS_PREMIUM) || + StringUtils.equalsIgnoreCase(memberStatus, GCConstants.MEMBER_STATUS_CHARTER); } public static String getGCMemberStatus() { return getString(R.string.pref_memberstatus, ""); } - public static boolean setGCMemberStatus(final String memberStatus) { + public static void setGCMemberStatus(final String memberStatus) { if (StringUtils.isBlank(memberStatus)) { - return remove(R.string.pref_memberstatus); + remove(R.string.pref_memberstatus); } - return putString(R.string.pref_memberstatus, memberStatus); + putString(R.string.pref_memberstatus, memberStatus); } public static ImmutablePair<String, String> getTokenPair(final int tokenPublicPrefKey, final int tokenSecretPrefKey) { @@ -375,10 +453,7 @@ public class Settings { } public static boolean isGCvoteLogin() { - final String preUsername = getString(R.string.pref_username, null); - final String prePassword = getString(R.string.pref_pass_vote, null); - - return !StringUtils.isBlank(preUsername) && !StringUtils.isBlank(prePassword); + return getGCvoteLogin() != null; } public static ImmutablePair<String, String> getGCvoteLogin() { @@ -396,19 +471,33 @@ public class Settings { return getString(R.string.pref_signature, StringUtils.EMPTY); } - public static boolean setCookieStore(final String cookies) { + public static void setCookieStore(final String cookies) { if (StringUtils.isBlank(cookies)) { // erase cookies - return remove(R.string.pref_cookiestore); + remove(R.string.pref_cookiestore); } // save cookies - return putString(R.string.pref_cookiestore, cookies); + putString(R.string.pref_cookiestore, cookies); } public static String getCookieStore() { return getString(R.string.pref_cookiestore, null); } + public static void setUseGooglePlayServices(final boolean value) { + putBoolean(R.string.pref_googleplayservices, value); + } + + public static boolean useGooglePlayServices() { + // By defaut, enable play services starting from ICS. + return CgeoApplication.getInstance().isGooglePlayServicesAvailable() && + getBoolean(R.string.pref_googleplayservices, VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH); + } + + public static boolean useLowPowerMode() { + return getBoolean(R.string.pref_lowpowermode, false); + } + /** * @param cacheType * The cache type used for future filtering @@ -442,12 +531,11 @@ public class Settings { return getString(R.string.pref_mapfile, null); } - public static boolean setMapFile(final String mapFile) { - final boolean result = putString(R.string.pref_mapfile, mapFile); + public static void setMapFile(final String mapFile) { + putString(R.string.pref_mapfile, mapFile); if (mapFile != null) { setMapFileDirectory(new File(mapFile).getParent()); } - return result; } public static String getMapFileDirectory() { @@ -462,10 +550,9 @@ public class Settings { return null; } - public static boolean setMapFileDirectory(final String mapFileDirectory) { - final boolean result = putString(R.string.pref_mapDirectory, mapFileDirectory); + public static void setMapFileDirectory(final String mapFileDirectory) { + putString(R.string.pref_mapDirectory, mapFileDirectory); MapsforgeMapProvider.getInstance().updateOfflineMaps(); - return result; } public static boolean isValidMapFile() { @@ -506,10 +593,11 @@ public class Settings { /** * @return User selected date format on GC.com - * @see GCLogin#GC_CUSTOM_DATE_FORMATS */ public static String getGcCustomDate() { - return getString(R.string.pref_gccustomdate, null); + // We might have some users whose stored value is null, which is invalid. In this case, we use the default. + return StringUtils.defaultString(getString(R.string.pref_gccustomdate, GCConstants.DEFAULT_GC_DATE), + GCConstants.DEFAULT_GC_DATE); } public static boolean isExcludeMyCaches() { @@ -572,11 +660,15 @@ public class Settings { return getBoolean(R.string.pref_sigautoinsert, false); } - public static boolean isUseImperialUnits() { - return getBoolean(R.string.pref_units, getImperialUnitsDefault()); + public static void setUseImperialUnits(final boolean useImperialUnits) { + putBoolean(R.string.pref_units_imperial, useImperialUnits); + } + + public static boolean useImperialUnits() { + return getBoolean(R.string.pref_units_imperial, useImperialUnitsByDefault()); } - static boolean getImperialUnitsDefault() { + static boolean useImperialUnitsByDefault() { final String countryCode = Locale.getDefault().getCountry(); return "US".equals(countryCode) // USA || "LR".equals(countryCode) // Liberia @@ -592,21 +684,55 @@ public class Settings { } public static boolean isMapTrail() { - return getBoolean(R.string.pref_maptrail, true); + return getBoolean(R.string.pref_maptrail, false); } public static void setMapTrail(final boolean showTrail) { putBoolean(R.string.pref_maptrail, showTrail); } - public static int getMapZoom() { - return getInt(R.string.pref_lastmapzoom, 14); + /** + * Get last used zoom of the internal map. Differentiate between two use cases for a map of multiple caches (e.g. + * live map) and the map of a single cache (which is often zoomed in more deep). + */ + public static int getMapZoom(final MapMode mapMode) { + if (mapMode == MapMode.SINGLE || mapMode == MapMode.COORDS) { + return getCacheZoom(); + } + return getMapZoom(); } - public static void setMapZoom(final int mapZoomLevel) { + public static void setMapZoom(final MapMode mapMode, final int zoomLevel) { + if (mapMode == MapMode.SINGLE || mapMode == MapMode.COORDS) { + setCacheZoom(zoomLevel); + } + else { + setMapZoom(zoomLevel); + } + } + + /** + * @return zoom used for the (live) map + */ + private static int getMapZoom() { + return Math.max(getInt(R.string.pref_lastmapzoom, 14), INITIAL_MAP_ZOOM_LIMIT); + } + + private static void setMapZoom(final int mapZoomLevel) { putInt(R.string.pref_lastmapzoom, mapZoomLevel); } + /** + * @return zoom used for the map of a single cache + */ + private static int getCacheZoom() { + return Math.max(getInt(R.string.pref_cache_zoom, 14), INITIAL_MAP_ZOOM_LIMIT); + } + + private static void setCacheZoom(final int zoomLevel) { + putInt(R.string.pref_cache_zoom, zoomLevel); + } + public static GeoPointImpl getMapCenter() { return getMapProvider().getMapItemFactory() .getGeoPointBase(new Geopoint(getInt(R.string.pref_lastmaplat, 0) / 1e6, @@ -627,7 +753,7 @@ public class Settings { // mapSource = MapProviderFactory.getMapSource(id); if (mapSource != null) { // don't use offline maps if the map file is not valid - if ((!(mapSource instanceof OfflineMapSource)) || (isValidMapFile())) { + if (!(mapSource instanceof OfflineMapSource) || isValidMapFile()) { return mapSource; } } @@ -646,9 +772,7 @@ public class Settings { private static final int HISTORY_SIZE = 10; /** - * convert old preference ids for maps (based on constant values) into new hash based ids - * - * @return + * Convert old preference ids for maps (based on constant values) into new hash based ids. */ // private static int getConvertedMapId() { // final int id = Integer.parseInt(getString(R.string.pref_mapsource, @@ -675,7 +799,7 @@ public class Settings { // return id; // } - public static void setMapSource(final MapSource newMapSource) { + public static synchronized void setMapSource(final MapSource newMapSource) { putString(R.string.pref_mapsource, String.valueOf(newMapSource.getNumericalId())); if (newMapSource instanceof OfflineMapSource) { setMapFile(((OfflineMapSource) newMapSource).getFileName()); @@ -704,11 +828,11 @@ public class Settings { } public static boolean isUseCompass() { - return getBoolean(R.string.pref_usecompass, true); + return useCompass; } - public static void setUseCompass(final boolean useCompass) { - putBoolean(R.string.pref_usecompass, useCompass); + public static void setUseCompass(final boolean value) { + useCompass = value; } public static boolean isLightSkin() { @@ -716,13 +840,13 @@ public class Settings { } @NonNull - public static String getKeyConsumerPublic() { - return keyConsumerPublic; + public static String getTwitterKeyConsumerPublic() { + return TWITTER_KEY_CONSUMER_PUBLIC; } @NonNull - public static String getKeyConsumerSecret() { - return keyConsumerSecret; + public static String getTwitterKeyConsumerSecret() { + return TWITTER_KEY_CONSUMER_SECRET; } public static String getWebDeviceCode() { @@ -734,13 +858,14 @@ public class Settings { } public static String getWebDeviceName() { - return getString(R.string.pref_webDeviceName, android.os.Build.MODEL); + return getString(R.string.pref_webDeviceName, Build.MODEL); } /** * @return The cache type used for filtering or ALL if no filter is active. * Returns never null */ + @NonNull public static CacheType getCacheType() { return CacheType.getById(getString(R.string.pref_cachetype, CacheType.ALL.id)); } @@ -838,11 +963,11 @@ public class Settings { String.valueOf(NavigationAppsEnum.INTERNAL_MAP.id))); } - public static Strategy getLiveMapStrategy() { - return Strategy.getById(getInt(R.string.pref_livemapstrategy, Strategy.AUTO.id)); + public static LivemapStrategy getLiveMapStrategy() { + return LivemapStrategy.getById(getInt(R.string.pref_livemapstrategy, LivemapStrategy.AUTO.id)); } - public static void setLiveMapStrategy(final Strategy strategy) { + public static void setLiveMapStrategy(final LivemapStrategy strategy) { putInt(R.string.pref_livemapstrategy, strategy.id); } @@ -850,14 +975,6 @@ public class Settings { return Log.isDebug(); } - public static boolean getHideLiveMapHint() { - return getBoolean(R.string.pref_hidelivemaphint, false); - } - - public static void setHideLiveHint(final boolean hide) { - putBoolean(R.string.pref_hidelivemaphint, hide); - } - public static int getLiveMapHintShowCount() { return getInt(R.string.pref_livemaphintshowcount, 0); } @@ -986,9 +1103,7 @@ public class Settings { } /** - * remember date of last field note export - * - * @param date + * Remember date of last field note export. */ public static void setFieldnoteExportDate(final long date) { putLong(R.string.pref_fieldNoteExportDate, date); @@ -999,9 +1114,7 @@ public class Settings { } /** - * remember the state of the "Upload" checkbox in the field notes export dialog - * - * @param upload + * Remember the state of the "Upload" checkbox in the field notes export dialog. */ public static void setFieldNoteExportUpload(final boolean upload) { putBoolean(R.string.pref_fieldNoteExportUpload, upload); @@ -1012,9 +1125,7 @@ public class Settings { } /** - * remember the state of the "Only new" checkbox in the field notes export dialog - * - * @param onlyNew + * Remember the state of the "Only new" checkbox in the field notes export dialog. */ public static void setFieldNoteExportOnlyNew(final boolean onlyNew) { putBoolean(R.string.pref_fieldNoteExportOnlyNew, onlyNew); @@ -1054,7 +1165,32 @@ public class Settings { return getBoolean(R.string.pref_hardware_acceleration, !HW_ACCEL_DISABLED_BY_DEFAULT); } - public static boolean setUseHardwareAcceleration(final boolean useHardwareAcceleration) { - return putBoolean(R.string.pref_hardware_acceleration, useHardwareAcceleration); + public static void setUseHardwareAcceleration(final boolean useHardwareAcceleration) { + putBoolean(R.string.pref_hardware_acceleration, useHardwareAcceleration); + } + + public static String getLastCacheLog() { + return getString(R.string.pref_last_cache_log, StringUtils.EMPTY); + } + + public static void setLastCacheLog(final String log) { + putString(R.string.pref_last_cache_log, log); + } + + public static String getLastTrackableLog() { + return getString(R.string.pref_last_trackable_log, StringUtils.EMPTY); + } + + public static void setLastTrackableLog(final String log) { + putString(R.string.pref_last_trackable_log, log); + } + + @Nullable + public static String getHomeLocation() { + return getString(R.string.pref_home_location, null); + } + + public static void setHomeLocation(@NonNull final String homeLocation) { + putString(R.string.pref_home_location, homeLocation); } } diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java index df6e680..6e3ba0e 100644 --- a/main/src/cgeo/geocaching/settings/SettingsActivity.java +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -1,7 +1,5 @@ package cgeo.geocaching.settings; -import butterknife.ButterKnife; - import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.DataStore; import cgeo.geocaching.Intents; @@ -14,13 +12,19 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.files.SimpleDirChooser; import cgeo.geocaching.maps.MapProviderFactory; import cgeo.geocaching.maps.interfaces.MapSource; +import cgeo.geocaching.network.AndroidBeam; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.utils.DatabaseBackupUtils; import cgeo.geocaching.utils.DebugUtils; import cgeo.geocaching.utils.Log; +import cgeo.geocaching.utils.RxUtils; import org.apache.commons.lang3.StringUtils; import org.openintents.intents.FileManagerIntents; +import rx.functions.Action0; +import rx.schedulers.Schedulers; + import android.app.ProgressDialog; import android.app.backup.BackupManager; import android.content.ActivityNotFoundException; @@ -90,12 +94,14 @@ public class SettingsActivity extends PreferenceActivity { setTheme(Settings.isLightSkin() && Build.VERSION.SDK_INT > 10 ? R.style.settings_light : R.style.settings); super.onCreate(savedInstanceState); - initHardwareAccelerationPreferences(); + initDeviceSpecificPreferences(); + initUnitPreferences(); SettingsActivity.addPreferencesFromResource(this, R.xml.preferences); initPreferences(); final Intent intent = getIntent(); openInitialScreen(intent.getIntExtra(INTENT_OPEN_SCREEN, 0)); + AndroidBeam.disable(this); } private void openInitialScreen(final int initialScreen) { @@ -126,6 +132,7 @@ public class SettingsActivity extends PreferenceActivity { initDefaultNavigationPreferences(); initBackupButtons(); initDbLocationPreference(); + initGeoDirPreferences(); initDebugPreference(); initBasicMemberPreferences(); initSend2CgeoPreferences(); @@ -143,7 +150,6 @@ public class SettingsActivity extends PreferenceActivity { R.string.pref_ecusername, R.string.pref_ecpassword, R.string.pref_ec_icons }) { bindSummaryToStringValue(k); } - getPreference(R.string.pref_units).setDefaultValue(Settings.getImperialUnitsDefault()); } private void initNavigationMenuPreferences() { @@ -278,7 +284,7 @@ public class SettingsActivity extends PreferenceActivity { /** * Fire up a directory chooser on click on the preference. * - * @see #onActivityResult() for processing of the selected directory + * The result can be processed using {@link android.app.Activity#onActivityResult}. * * @param dct * type of directory to be selected @@ -297,7 +303,7 @@ public class SettingsActivity extends PreferenceActivity { dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, getString(android.R.string.ok)); startActivityForResult(dirChooser, dct.requestCode); - } catch (final android.content.ActivityNotFoundException ex) { + } catch (final ActivityNotFoundException ignored) { // OI file manager not available final Intent dirChooser = new Intent(this, SimpleDirChooser.class); dirChooser.putExtra(Intents.EXTRA_START_DIR, startDirectory); @@ -323,13 +329,14 @@ public class SettingsActivity extends PreferenceActivity { backup.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(final Preference preference) { - return DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() { + DatabaseBackupUtils.createBackup(SettingsActivity.this, new Runnable() { @Override public void run() { VALUE_CHANGE_LISTENER.onPreferenceChange(SettingsActivity.this.getPreference(R.string.pref_fakekey_preference_backup_info), ""); } }); + return true; } }); @@ -354,37 +361,41 @@ public class SettingsActivity extends PreferenceActivity { final Resources res = getResources(); final SettingsActivity activity = SettingsActivity.this; final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_maintenance), res.getString(R.string.init_maintenance_directories), true, false); - new Thread() { + RxUtils.andThenOnUi(Schedulers.io(), new Action0() { @Override - public void run() { + public void call() { DataStore.removeObsoleteCacheDirectories(); - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - dialog.dismiss(); - } - }); } - }.start(); - + }, new Action0() { + @Override + public void call() { + dialog.dismiss(); + } + }); return true; - } - }); + } + }); final Preference memoryDumpPref = getPreference(R.string.pref_memory_dump); memoryDumpPref .setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override public boolean onPreferenceClick( - final Preference preference) { - DebugUtils.createMemoryDump(SettingsActivity.this); - return true; - } - }); + @Override + public boolean onPreferenceClick( + final Preference preference) { + DebugUtils.createMemoryDump(SettingsActivity.this); + return true; + } + }); } - public static void initHardwareAccelerationPreferences() { - // We have to ensure that the preference is initialized so that devices with hardware acceleration disabled - // get the appropriate value. + public static void initDeviceSpecificPreferences() { + // We have to ensure that those preferences are initialized so that devices with specific default values + // will get the appropriate ones. Settings.setUseHardwareAcceleration(Settings.useHardwareAcceleration()); + Settings.setUseGooglePlayServices(Settings.useGooglePlayServices()); + } + + private static void initUnitPreferences() { + Settings.setUseImperialUnits(Settings.useImperialUnits()); } private void initDbLocationPreference() { @@ -413,6 +424,28 @@ public class SettingsActivity extends PreferenceActivity { }); } + private void initGeoDirPreferences() { + final Sensors sensors = Sensors.getInstance(); + final Preference playServices = getPreference(R.string.pref_googleplayservices); + playServices.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(final Preference preference, final Object newValue) { + sensors.setupGeoDataObservables((Boolean) newValue, Settings.useLowPowerMode()); + return true; + } + }); + playServices.setEnabled(CgeoApplication.getInstance().isGooglePlayServicesAvailable()); + getPreference(R.string.pref_lowpowermode).setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(final Preference preference, final Object newValue) { + final Boolean useLowPower = (Boolean) newValue; + sensors.setupGeoDataObservables(Settings.useGooglePlayServices(), useLowPower); + sensors.setupDirectionObservable(useLowPower); + return true; + } + }); + } + void initBasicMemberPreferences() { getPreference(R.string.preference_screen_basicmembers) .setEnabled(!Settings.isGCPremiumMember()); @@ -570,7 +603,7 @@ public class SettingsActivity extends PreferenceActivity { final int mapSourceId = Integer.parseInt(stringValue); mapSource = MapProviderFactory.getMapSource(mapSourceId); } catch (final NumberFormatException e) { - Log.e("SettingsActivity.onPreferenceChange: bad source id '" + stringValue + "'"); + Log.e("SettingsActivity.onPreferenceChange: bad source id '" + stringValue + "'", e); mapSource = null; } // If there is no corresponding map source (because some map sources were @@ -676,8 +709,6 @@ public class SettingsActivity extends PreferenceActivity { /** * auto-care for the summary of the preference of string type with this key - * - * @param key */ private void bindSummaryToStringValue(final int key) { diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java index 968dce5..d7c46e1 100644 --- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java +++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java @@ -9,7 +9,7 @@ import org.apache.commons.lang3.StringUtils; * abstract super implementation for all cache comparators * */ -public abstract class AbstractCacheComparator implements CacheComparator { +abstract class AbstractCacheComparator implements CacheComparator { @Override public final int compare(final Geocache cache1, final Geocache cache2) { @@ -35,9 +35,11 @@ public abstract class AbstractCacheComparator implements CacheComparator { * Check necessary preconditions (like missing fields) before running the comparison itself. * Caches not filling the conditions will be placed last, sorted by Geocode. * - * The default returns <code>true</code> and can be overridden if needed in child classes. - * + * The default implementation returns <code>true</code> and can be overridden if needed in sub classes. + * * @param cache + * the cache to be sorted + * * @return <code>true</code> if the cache holds the necessary data to be compared meaningfully */ @SuppressWarnings("static-method") @@ -51,8 +53,6 @@ public abstract class AbstractCacheComparator implements CacheComparator { * A cache is smaller than another cache if it is desirable to show it first when presented to the user. * For example, a highly rated cache must be considered smaller than a poorly rated one. * - * @param cache1 - * @param cache2 * @return an integer < 0 if cache1 is less than cache2, 0 if they are equal, and > 0 if cache1 is greater than * cache2. */ diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java index 7913941..347eb44 100644 --- a/main/src/cgeo/geocaching/sorting/DateComparator.java +++ b/main/src/cgeo/geocaching/sorting/DateComparator.java @@ -1,7 +1,7 @@ package cgeo.geocaching.sorting; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; +import cgeo.geocaching.sensors.Sensors; import java.util.ArrayList; import java.util.Date; @@ -9,21 +9,16 @@ import java.util.Date; /** * compares caches by date */ -public class DateComparator extends AbstractCacheComparator { +class DateComparator extends AbstractCacheComparator { @Override - protected int compareCaches(Geocache cache1, Geocache cache2) { + protected int compareCaches(final Geocache cache1, final Geocache cache2) { final Date date1 = cache1.getHiddenDate(); final Date date2 = cache2.getHiddenDate(); if (date1 != null && date2 != null) { final int dateDifference = date1.compareTo(date2); - // for equal dates, sort by distance if (dateDifference == 0) { - final ArrayList<Geocache> list = new ArrayList<>(); - list.add(cache1); - list.add(cache2); - final DistanceComparator distanceComparator = new DistanceComparator(CgeoApplication.getInstance().currentGeo().getCoords(), list); - return distanceComparator.compare(cache1, cache2); + return sortSameDate(cache1, cache2); } return dateDifference; } @@ -35,4 +30,13 @@ public class DateComparator extends AbstractCacheComparator { } return 0; } + + @SuppressWarnings("static-method") + protected int sortSameDate(final Geocache cache1, final Geocache cache2) { + final ArrayList<Geocache> list = new ArrayList<>(); + list.add(cache1); + list.add(cache2); + final DistanceComparator distanceComparator = new DistanceComparator(Sensors.getInstance().currentGeo().getCoords(), list); + return distanceComparator.compare(cache1, cache2); + } } diff --git a/main/src/cgeo/geocaching/sorting/DifficultyComparator.java b/main/src/cgeo/geocaching/sorting/DifficultyComparator.java index 459f38d..10463c8 100644 --- a/main/src/cgeo/geocaching/sorting/DifficultyComparator.java +++ b/main/src/cgeo/geocaching/sorting/DifficultyComparator.java @@ -6,10 +6,10 @@ import cgeo.geocaching.Geocache; * sorts caches by difficulty * */ -public class DifficultyComparator extends AbstractCacheComparator { +class DifficultyComparator extends AbstractCacheComparator { @Override - protected boolean canCompare(Geocache cache) { + protected boolean canCompare(final Geocache cache) { return cache.getDifficulty() != 0.0; } diff --git a/main/src/cgeo/geocaching/sorting/DistanceComparator.java b/main/src/cgeo/geocaching/sorting/DistanceComparator.java index b3b751b..f400583 100644 --- a/main/src/cgeo/geocaching/sorting/DistanceComparator.java +++ b/main/src/cgeo/geocaching/sorting/DistanceComparator.java @@ -1,7 +1,7 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import java.util.ArrayList; import java.util.List; @@ -28,7 +28,8 @@ public class DistanceComparator extends AbstractCacheComparator { public DistanceComparator(final Geopoint coords, final List<Geocache> list) { this.coords = coords; - this.list = list; + // create new list so we can iterate over the list in parallel with the cache list adapter + this.list = new ArrayList<>(list); } /** diff --git a/main/src/cgeo/geocaching/sorting/EventDateComparator.java b/main/src/cgeo/geocaching/sorting/EventDateComparator.java index 197946a..efeeb5d 100644 --- a/main/src/cgeo/geocaching/sorting/EventDateComparator.java +++ b/main/src/cgeo/geocaching/sorting/EventDateComparator.java @@ -1,5 +1,7 @@ package cgeo.geocaching.sorting; +import cgeo.geocaching.Geocache; + /** * Compares caches by date. Used only for event caches. */ @@ -7,4 +9,16 @@ public class EventDateComparator extends DateComparator { final static public EventDateComparator singleton = new EventDateComparator(); + @Override + protected int sortSameDate(final Geocache left, final Geocache right) { + return compare(left.guessEventTimeMinutes(), right.guessEventTimeMinutes()); + } + + /** + * copy of {@link Integer#compare(int, int)}, as that is not available on lower API levels + * + */ + private static int compare(final int left, final int right) { + return left < right ? -1 : (left == right ? 0 : 1); + } } diff --git a/main/src/cgeo/geocaching/sorting/FindsComparator.java b/main/src/cgeo/geocaching/sorting/FindsComparator.java index 7f2ef50..a4c0686 100644 --- a/main/src/cgeo/geocaching/sorting/FindsComparator.java +++ b/main/src/cgeo/geocaching/sorting/FindsComparator.java @@ -2,17 +2,17 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; -public class FindsComparator extends AbstractCacheComparator { +class FindsComparator extends AbstractCacheComparator { @Override - protected boolean canCompare(Geocache cache) { + protected boolean canCompare(final Geocache cache) { return cache.getLogCounts() != null; } @Override - protected int compareCaches(Geocache cache1, Geocache cache2) { - int finds1 = cache1.getFindsCount(); - int finds2 = cache2.getFindsCount(); + protected int compareCaches(final Geocache cache1, final Geocache cache2) { + final int finds1 = cache1.getFindsCount(); + final int finds2 = cache2.getFindsCount(); return finds2 - finds1; } diff --git a/main/src/cgeo/geocaching/sorting/GeocodeComparator.java b/main/src/cgeo/geocaching/sorting/GeocodeComparator.java index e700f13..30a2fc8 100644 --- a/main/src/cgeo/geocaching/sorting/GeocodeComparator.java +++ b/main/src/cgeo/geocaching/sorting/GeocodeComparator.java @@ -6,7 +6,7 @@ import cgeo.geocaching.Geocache; * sorts caches by geo code, therefore effectively sorting by cache age * */ -public class GeocodeComparator extends AbstractCacheComparator { +class GeocodeComparator extends AbstractCacheComparator { @Override protected boolean canCompare(final Geocache cache) { diff --git a/main/src/cgeo/geocaching/sorting/InventoryComparator.java b/main/src/cgeo/geocaching/sorting/InventoryComparator.java index 9d19b64..13eadcc 100644 --- a/main/src/cgeo/geocaching/sorting/InventoryComparator.java +++ b/main/src/cgeo/geocaching/sorting/InventoryComparator.java @@ -5,7 +5,7 @@ import cgeo.geocaching.Geocache; /** * sorts caches by number of items in inventory */ -public class InventoryComparator extends AbstractCacheComparator { +class InventoryComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { diff --git a/main/src/cgeo/geocaching/sorting/InverseComparator.java b/main/src/cgeo/geocaching/sorting/InverseComparator.java index 1dc76e2..0da351f 100644 --- a/main/src/cgeo/geocaching/sorting/InverseComparator.java +++ b/main/src/cgeo/geocaching/sorting/InverseComparator.java @@ -10,12 +10,12 @@ public class InverseComparator implements CacheComparator { private final CacheComparator originalComparator; - public InverseComparator(CacheComparator comparator) { + public InverseComparator(final CacheComparator comparator) { this.originalComparator = comparator; } @Override - public int compare(Geocache lhs, Geocache rhs) { + public int compare(final Geocache lhs, final Geocache rhs) { return originalComparator.compare(rhs, lhs); } diff --git a/main/src/cgeo/geocaching/sorting/NameComparator.java b/main/src/cgeo/geocaching/sorting/NameComparator.java index 2941b1c..ab7bbcb 100644 --- a/main/src/cgeo/geocaching/sorting/NameComparator.java +++ b/main/src/cgeo/geocaching/sorting/NameComparator.java @@ -1,22 +1,27 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; +import cgeo.geocaching.utils.TextUtils; import org.apache.commons.lang3.StringUtils; +import java.text.Collator; + /** * sorts caches by name * */ -public class NameComparator extends AbstractCacheComparator { +class NameComparator extends AbstractCacheComparator { + + private final Collator collator = TextUtils.getCollator(); @Override - protected boolean canCompare(Geocache cache) { + protected boolean canCompare(final Geocache cache) { return StringUtils.isNotBlank(cache.getName()); } @Override - protected int compareCaches(Geocache cache1, Geocache cache2) { - return cache1.getNameForSorting().compareToIgnoreCase(cache2.getNameForSorting()); + protected int compareCaches(final Geocache cache1, final Geocache cache2) { + return collator.compare(cache1.getNameForSorting(), cache2.getNameForSorting()); } } diff --git a/main/src/cgeo/geocaching/sorting/PopularityComparator.java b/main/src/cgeo/geocaching/sorting/PopularityComparator.java index 2dbee68..58b3b4c 100644 --- a/main/src/cgeo/geocaching/sorting/PopularityComparator.java +++ b/main/src/cgeo/geocaching/sorting/PopularityComparator.java @@ -6,7 +6,7 @@ import cgeo.geocaching.Geocache; * sorts caches by popularity (favorite count) * */ -public class PopularityComparator extends AbstractCacheComparator { +class PopularityComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { diff --git a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java index 57a69ee..4c2d914 100644 --- a/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java +++ b/main/src/cgeo/geocaching/sorting/PopularityRatioComparator.java @@ -8,12 +8,12 @@ import cgeo.geocaching.Geocache; /** * sorts caches by popularity ratio (favorites per find in %). */ -public class PopularityRatioComparator extends AbstractCacheComparator { +class PopularityRatioComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { - int finds1 = cache1.getFindsCount(); - int finds2 = cache2.getFindsCount(); + final int finds1 = cache1.getFindsCount(); + final int finds2 = cache2.getFindsCount(); float ratio1 = 0.0f; if (finds1 != 0) { @@ -26,7 +26,8 @@ public class PopularityRatioComparator extends AbstractCacheComparator { if ((ratio2 - ratio1) > 0.0f) { return 1; - } else if ((ratio2 - ratio1) < 0.0f) { + } + if ((ratio2 - ratio1) < 0.0f) { return -1; } diff --git a/main/src/cgeo/geocaching/sorting/RatingComparator.java b/main/src/cgeo/geocaching/sorting/RatingComparator.java index 6f2c615..62854fe 100644 --- a/main/src/cgeo/geocaching/sorting/RatingComparator.java +++ b/main/src/cgeo/geocaching/sorting/RatingComparator.java @@ -6,7 +6,7 @@ import cgeo.geocaching.Geocache; * sorts caches by gcvote.com rating * */ -public class RatingComparator extends AbstractCacheComparator { +class RatingComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { diff --git a/main/src/cgeo/geocaching/sorting/SizeComparator.java b/main/src/cgeo/geocaching/sorting/SizeComparator.java index c8de586..8cb5178 100644 --- a/main/src/cgeo/geocaching/sorting/SizeComparator.java +++ b/main/src/cgeo/geocaching/sorting/SizeComparator.java @@ -6,15 +6,10 @@ import cgeo.geocaching.Geocache; * sorts caches by size * */ -public class SizeComparator extends AbstractCacheComparator { +class SizeComparator extends AbstractCacheComparator { @Override - protected boolean canCompare(Geocache cache) { - return cache.getSize() != null; - } - - @Override - protected int compareCaches(Geocache cache1, Geocache cache2) { + protected int compareCaches(final Geocache cache1, final Geocache cache2) { return cache2.getSize().comparable - cache1.getSize().comparable; } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/sorting/SortActionProvider.java b/main/src/cgeo/geocaching/sorting/SortActionProvider.java index 6251984..e6db330 100644 --- a/main/src/cgeo/geocaching/sorting/SortActionProvider.java +++ b/main/src/cgeo/geocaching/sorting/SortActionProvider.java @@ -136,9 +136,7 @@ public class SortActionProvider extends ActionProvider implements OnMenuItemClic final CacheComparator comparator = cacheComparator.newInstance(); onClickListener.call(comparator); } - } catch (final InstantiationException e) { - Log.e("selectComparator", e); - } catch (final IllegalAccessException e) { + } catch (final InstantiationException | IllegalAccessException e) { Log.e("selectComparator", e); } } diff --git a/main/src/cgeo/geocaching/sorting/StateComparator.java b/main/src/cgeo/geocaching/sorting/StateComparator.java index 9488bd9..e4403f8 100644 --- a/main/src/cgeo/geocaching/sorting/StateComparator.java +++ b/main/src/cgeo/geocaching/sorting/StateComparator.java @@ -6,7 +6,7 @@ import cgeo.geocaching.Geocache; * sort caches by state (normal, disabled, archived) * */ -public class StateComparator extends AbstractCacheComparator { +class StateComparator extends AbstractCacheComparator { @Override protected int compareCaches(final Geocache cache1, final Geocache cache2) { diff --git a/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java b/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java index b718d3b..fbe3226 100644 --- a/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java +++ b/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java @@ -2,10 +2,10 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; -public class StorageTimeComparator extends AbstractCacheComparator { +class StorageTimeComparator extends AbstractCacheComparator { @Override - protected int compareCaches(Geocache cache1, Geocache cache2) { + protected int compareCaches(final Geocache cache1, final Geocache cache2) { if (cache1.getUpdated() < cache2.getUpdated()) { return -1; } diff --git a/main/src/cgeo/geocaching/sorting/TerrainComparator.java b/main/src/cgeo/geocaching/sorting/TerrainComparator.java index 9bbb5f7..e882025 100644 --- a/main/src/cgeo/geocaching/sorting/TerrainComparator.java +++ b/main/src/cgeo/geocaching/sorting/TerrainComparator.java @@ -6,7 +6,7 @@ import cgeo.geocaching.Geocache; * sorts caches by terrain rating * */ -public class TerrainComparator extends AbstractCacheComparator { +class TerrainComparator extends AbstractCacheComparator { @Override protected boolean canCompare(final Geocache cache) { diff --git a/main/src/cgeo/geocaching/sorting/VoteComparator.java b/main/src/cgeo/geocaching/sorting/VoteComparator.java index cd4ad7e..5cf39d7 100644 --- a/main/src/cgeo/geocaching/sorting/VoteComparator.java +++ b/main/src/cgeo/geocaching/sorting/VoteComparator.java @@ -5,10 +5,10 @@ import cgeo.geocaching.Geocache; /** * sorts caches by the users own voting (if available at all) */ -public class VoteComparator extends AbstractCacheComparator { +class VoteComparator extends AbstractCacheComparator { @Override - protected int compareCaches(Geocache cache1, Geocache cache2) { + protected int compareCaches(final Geocache cache1, final Geocache cache2) { // if there is no vote available, put that cache at the end of the list return Float.compare(cache2.getMyVote(), cache1.getMyVote()); } diff --git a/main/src/cgeo/geocaching/speech/SpeechService.java b/main/src/cgeo/geocaching/speech/SpeechService.java index fbd2d7e..b22e061 100644 --- a/main/src/cgeo/geocaching/speech/SpeechService.java +++ b/main/src/cgeo/geocaching/speech/SpeechService.java @@ -1,10 +1,11 @@ package cgeo.geocaching.speech; +import cgeo.geocaching.Intents; import cgeo.geocaching.R; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; -import cgeo.geocaching.sensors.IGeoData; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; @@ -31,7 +32,6 @@ public class SpeechService extends Service implements OnInitListener { private static final int SPEECH_MINPAUSE_SECONDS = 5; private static final int SPEECH_MAXPAUSE_SECONDS = 30; - private static final String EXTRA_TARGET_COORDS = "target"; private static Activity startingActivity; private static boolean isRunning = false; /** @@ -47,7 +47,7 @@ public class SpeechService extends Service implements OnInitListener { final GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override - public void updateGeoDir(final IGeoData newGeo, final float newDirection) { + public void updateGeoDir(final GeoData newGeo, final float newDirection) { position = newGeo.getCoords(); direction = newDirection; // avoid any calculation, if the delay since the last output is not long enough @@ -152,11 +152,12 @@ public class SpeechService extends Service implements OnInitListener { @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { if (intent != null) { - target = intent.getParcelableExtra(EXTRA_TARGET_COORDS); + target = intent.getParcelableExtra(Intents.EXTRA_COORDS); } return START_NOT_STICKY; // service can be stopped by system, if under memory pressure } + @SuppressWarnings("deprecation") private void speak(final String text) { if (!initialized) { return; @@ -168,7 +169,7 @@ public class SpeechService extends Service implements OnInitListener { isRunning = true; startingActivity = activity; final Intent talkingService = new Intent(activity, SpeechService.class); - talkingService.putExtra(EXTRA_TARGET_COORDS, dstCoords); + talkingService.putExtra(Intents.EXTRA_COORDS, dstCoords); activity.startService(talkingService); } diff --git a/main/src/cgeo/geocaching/speech/TextFactory.java b/main/src/cgeo/geocaching/speech/TextFactory.java index eb780c6..3f1f142 100644 --- a/main/src/cgeo/geocaching/speech/TextFactory.java +++ b/main/src/cgeo/geocaching/speech/TextFactory.java @@ -2,8 +2,8 @@ package cgeo.geocaching.speech; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.IConversion; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.IConversion; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.AngleUtils; @@ -21,17 +21,17 @@ import java.util.Locale; * on unit expressions. */ public class TextFactory { - public static String getText(Geopoint position, Geopoint target, float direction) { + public static String getText(final Geopoint position, final Geopoint target, final float direction) { if (position == null || target == null) { return null; } return getDirection(position, target, direction) + ". " + getDistance(position, target); } - private static String getDistance(Geopoint position, Geopoint target) { + private static String getDistance(final Geopoint position, final Geopoint target) { final float kilometers = position.distanceTo(target); - if (Settings.isUseImperialUnits()) { + if (Settings.useImperialUnits()) { return getDistance(kilometers / IConversion.MILES_TO_KILOMETER, (int) (kilometers * 1000.0 * IConversion.METERS_TO_FEET), 3.0f, 0.2f, 300, @@ -44,9 +44,9 @@ public class TextFactory { R.plurals.tts_meters, R.string.tts_one_meter); } - private static String getDistance(float farDistance, int nearDistance, - float farFarAway, float farNearAway, int nearFarAway, - int farId, int farOneId, int nearId, int nearOneId) { + private static String getDistance(final float farDistance, final int nearDistance, + final float farFarAway, final float farNearAway, final int nearFarAway, + final int farId, final int farOneId, final int nearId, final int nearOneId) { if (farDistance >= farFarAway) { // example: "5 kilometers" - always without decimal digits final int quantity = Math.round(farDistance); @@ -84,15 +84,15 @@ public class TextFactory { return getQuantityString(nearId, quantity, String.valueOf(quantity)); } - private static String getString(int resourceId, Object... formatArgs) { + private static String getString(final int resourceId, final Object... formatArgs) { return CgeoApplication.getInstance().getString(resourceId, formatArgs); } - private static String getQuantityString(int resourceId, int quantity, Object... formatArgs) { + private static String getQuantityString(final int resourceId, final int quantity, final Object... formatArgs) { return CgeoApplication.getInstance().getResources().getQuantityString(resourceId, quantity, formatArgs); } - private static String getDirection(Geopoint position, Geopoint target, float direction) { + private static String getDirection(final Geopoint position, final Geopoint target, final float direction) { final int bearing = (int) position.bearingTo(target); final int degrees = (int) AngleUtils.normalize(bearing - direction); diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index c89c0b6..0e5ebfa 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -6,10 +6,11 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; import cgeo.geocaching.Trackable; import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter.Format; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter.Format; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; +import cgeo.geocaching.network.OAuthTokens; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; @@ -17,6 +18,7 @@ import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; import ch.boye.httpclientandroidlib.HttpResponse; + import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -25,7 +27,7 @@ public final class Twitter { private static final String HASH_PREFIX_WITH_BLANK = " #"; private static final int MAX_TWEET_SIZE = 140; - public static void postTweetCache(String geocode, final @Nullable LogEntry logEntry) { + public static void postTweetCache(final String geocode, final @Nullable LogEntry logEntry) { final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); if (cache == null) { return; @@ -33,7 +35,7 @@ public final class Twitter { postTweet(CgeoApplication.getInstance(), getStatusMessage(cache, logEntry), null); } - public static void postTweetTrackable(String geocode, final @Nullable LogEntry logEntry) { + public static void postTweetTrackable(final String geocode, final @Nullable LogEntry logEntry) { final Trackable trackable = DataStore.loadTrackable(geocode); if (trackable == null) { return; @@ -48,7 +50,7 @@ public final class Twitter { try { final String status = shortenToMaxSize(statusIn); - Parameters parameters = new Parameters("status", status); + final Parameters parameters = new Parameters("status", status); if (coords != null) { parameters.put( "lat", coords.format(Format.LAT_DECDEGREE_RAW), @@ -56,7 +58,7 @@ public final class Twitter { "display_coordinates", "true"); } - OAuth.signOAuth("api.twitter.com", "/1.1/statuses/update.json", "POST", true, parameters, Settings.getTokenPublic(), Settings.getTokenSecret(), Settings.getKeyConsumerPublic(), Settings.getKeyConsumerSecret()); + OAuth.signOAuth("api.twitter.com", "/1.1/statuses/update.json", "POST", true, parameters, new OAuthTokens(Settings.getTokenPublic(), Settings.getTokenSecret()), Settings.getTwitterKeyConsumerPublic(), Settings.getTwitterKeyConsumerSecret()); final HttpResponse httpResponse = Network.postRequest("https://api.twitter.com/1.1/statuses/update.json", parameters); if (httpResponse != null) { if (httpResponse.getStatusLine().getStatusCode() == 200) { @@ -67,13 +69,13 @@ public final class Twitter { } else { Log.e("Tweet could not be posted. Reason: httpResponse Object is null"); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("Twitter.postTweet", e); } } private static String shortenToMaxSize(final String status) { - String result = StringUtils.trim(status); + final String result = StringUtils.trim(status); if (StringUtils.length(result) > MAX_TWEET_SIZE) { return StringUtils.substring(result, 0, MAX_TWEET_SIZE - 1) + '…'; } @@ -98,7 +100,7 @@ public final class Twitter { } private static String appendHashTags(final String status) { - StringBuilder builder = new StringBuilder(status); + final StringBuilder builder = new StringBuilder(status); appendHashTag(builder, "cgeo"); appendHashTag(builder, "geocaching"); return builder.toString(); diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java index 97332d3..6df417b 100644 --- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java @@ -1,7 +1,7 @@ package cgeo.geocaching.twitter; import cgeo.geocaching.R; -import cgeo.geocaching.network.OAuthAuthorizationActivity; +import cgeo.geocaching.activity.OAuthAuthorizationActivity; import cgeo.geocaching.settings.Settings; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -15,8 +15,8 @@ public class TwitterAuthorizationActivity extends OAuthAuthorizationActivity { "/oauth/authorize", "/oauth/access_token", true, - Settings.getKeyConsumerPublic(), - Settings.getKeyConsumerSecret(), + Settings.getTwitterKeyConsumerPublic(), + Settings.getTwitterKeyConsumerSecret(), "callback://www.cgeo.org/twitter/"); @Override diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java index 06fa1fa..40d077e 100644 --- a/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java +++ b/main/src/cgeo/geocaching/ui/AbstractCachingListViewPageViewCreator.java @@ -30,10 +30,10 @@ public abstract class AbstractCachingListViewPageViewCreator extends AbstractCac if (view == null) { return null; } - int position = view.getFirstVisiblePosition(); - View child = view.getChildAt(0); - int positionFromTop = (child == null) ? 0 : child.getTop(); - Bundle state = new Bundle(); + final int position = view.getFirstVisiblePosition(); + final View child = view.getChildAt(0); + final int positionFromTop = (child == null) ? 0 : child.getTop(); + final Bundle state = new Bundle(); state.putInt(STATE_POSITION, position); state.putInt(STATE_POSITION_FROM_TOP, positionFromTop); return state; @@ -44,12 +44,12 @@ public abstract class AbstractCachingListViewPageViewCreator extends AbstractCac * */ @Override - public void setViewState(@NonNull Bundle state) { + public void setViewState(@NonNull final Bundle state) { if (view == null) { return; } - int logViewPosition = state.getInt(STATE_POSITION); - int logViewPositionFromTop = state.getInt(STATE_POSITION_FROM_TOP); + final int logViewPosition = state.getInt(STATE_POSITION); + final int logViewPositionFromTop = state.getInt(STATE_POSITION_FROM_TOP); view.setSelectionFromTop(logViewPosition, logViewPositionFromTop); } diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java index 306c686..60e8b2d 100644 --- a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java +++ b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java @@ -14,7 +14,6 @@ import android.view.ViewGroup; /** * View creator which destroys the created view on every {@link #notifyDataSetChanged()}. * - * @param <ViewClass> */ public abstract class AbstractCachingPageViewCreator<ViewClass extends View> implements PageViewCreator { diff --git a/main/src/cgeo/geocaching/ui/AbstractImageAdapter.java b/main/src/cgeo/geocaching/ui/AbstractImageAdapter.java new file mode 100644 index 0000000..22ec603 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/AbstractImageAdapter.java @@ -0,0 +1,66 @@ +package cgeo.geocaching.ui; + +import cgeo.geocaching.R; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.ImageView; + +import java.util.List; + +public abstract class AbstractImageAdapter extends BaseAdapter { + private final Context context; + // references to our images + private final List<Integer> imageIds; + private final int imageWidth; + + public AbstractImageAdapter(final Context context, final GridView gridView, final List<Integer> imageIds) { + this.context = context; + this.imageIds = imageIds; + + final Drawable drawable = context.getResources().getDrawable(imageIds.get(0)); + imageWidth = drawable.getIntrinsicWidth(); + + // fix the column width, now that we know the images + gridView.setColumnWidth(getImageWidth()); + } + + @Override + public int getCount() { + return imageIds.size(); + } + + @Override + public Object getItem(final int position) { + return null; + } + + @Override + public long getItemId(final int position) { + return 0; + } + + // create a new ImageView for each item referenced by the Adapter + @Override + public View getView(final int position, final View convertView, final ViewGroup parent) { + final ImageView imageView; + if (convertView == null) { // if it's not recycled, initialize some attributes + imageView = (ImageView) LayoutInflater.from(context).inflate(R.layout.grid_image, null); + } else { + imageView = (ImageView) convertView; + } + + imageView.setImageResource(imageIds.get(position)); + return imageView; + } + + int getImageWidth() { + return imageWidth; + } + +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java b/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java new file mode 100644 index 0000000..fbea675 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/AbstractMenuActionProvider.java @@ -0,0 +1,24 @@ +package cgeo.geocaching.ui; + +import android.content.Context; +import android.support.v4.view.ActionProvider; +import android.view.View; + +public abstract class AbstractMenuActionProvider extends ActionProvider { + + public AbstractMenuActionProvider(final Context context) { + super(context); + } + + @Override + public boolean hasSubMenu() { + return true; + } + + @Override + public View onCreateActionView() { + // must return null, otherwise the menu will not work + return null; + } + +} diff --git a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java index f26cb53..1efa15e 100644 --- a/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java +++ b/main/src/cgeo/geocaching/ui/AbstractUserClickListener.java @@ -24,7 +24,7 @@ abstract class AbstractUserClickListener implements View.OnClickListener { } @Override - public void onClick(View view) { + public void onClick(final View view) { if (view == null) { return; } @@ -45,8 +45,8 @@ abstract class AbstractUserClickListener implements View.OnClickListener { final AbstractActivity activity = (AbstractActivity) view.getContext(); final Resources res = activity.getResources(); - ArrayList<String> labels = new ArrayList<>(userActions.size()); - for (UserAction action : userActions) { + final ArrayList<String> labels = new ArrayList<>(userActions.size()); + for (final UserAction action : userActions) { labels.add(res.getString(action.displayResourceId)); } final CharSequence[] items = labels.toArray(new String[labels.size()]); @@ -55,7 +55,7 @@ abstract class AbstractUserClickListener implements View.OnClickListener { builder.setTitle(res.getString(R.string.user_menu_title) + " " + userName); builder.setItems(items, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int item) { + public void onClick(final DialogInterface dialog, final int item) { userActions.get(item).run(new Context(userName, activity)); } }); diff --git a/main/src/cgeo/geocaching/ui/AbstractViewHolder.java b/main/src/cgeo/geocaching/ui/AbstractViewHolder.java index b1cb719..0233bf0 100644 --- a/main/src/cgeo/geocaching/ui/AbstractViewHolder.java +++ b/main/src/cgeo/geocaching/ui/AbstractViewHolder.java @@ -11,7 +11,7 @@ import android.view.View; */ public abstract class AbstractViewHolder { - protected AbstractViewHolder(View view) { + protected AbstractViewHolder(final View view) { ButterKnife.inject(this, view); view.setTag(this); } diff --git a/main/src/cgeo/geocaching/ui/AddressListAdapter.java b/main/src/cgeo/geocaching/ui/AddressListAdapter.java index 81b6c23..901bffc 100644 --- a/main/src/cgeo/geocaching/ui/AddressListAdapter.java +++ b/main/src/cgeo/geocaching/ui/AddressListAdapter.java @@ -3,12 +3,13 @@ package cgeo.geocaching.ui; import butterknife.InjectView; import cgeo.geocaching.CacheListActivity; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.sensors.Sensors; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.location.Address; @@ -23,7 +24,7 @@ import java.util.ArrayList; public class AddressListAdapter extends ArrayAdapter<Address> { final private LayoutInflater inflater; - final private Geopoint location; + @NonNull final private Geopoint location; protected static final class ViewHolder extends AbstractViewHolder { @InjectView(R.id.label) protected TextView label; @@ -37,7 +38,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> { public AddressListAdapter(final Activity context) { super(context, 0); inflater = context.getLayoutInflater(); - location = CgeoApplication.getInstance().currentGeo().getCoords(); + location = Sensors.getInstance().currentGeo().getCoords(); } @Override @@ -72,7 +73,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> { } private CharSequence getDistanceText(final Address address) { - if (location != null && address.hasLatitude() && address.hasLongitude()) { + if (address.hasLatitude() && address.hasLongitude()) { return Units.getDistanceFromKilometers(location.distanceTo(new Geopoint(address.getLatitude(), address.getLongitude()))); } diff --git a/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java b/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java index d4c2e10..57c9db0 100644 --- a/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java +++ b/main/src/cgeo/geocaching/ui/AnchorAwareLinkMovementMethod.java @@ -26,10 +26,10 @@ public class AnchorAwareLinkMovementMethod extends LinkMovementMethod { } @Override - public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { + public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) { try { return super.onTouchEvent(widget, buffer, event); - } catch (Exception e) { + } catch (final Exception ignored) { // local links to anchors don't work } return false; diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java index 40cd726..e2af419 100644 --- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java +++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java @@ -2,31 +2,29 @@ package cgeo.geocaching.ui; import butterknife.ButterKnife; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; +import cgeo.geocaching.ICoordinates; import cgeo.geocaching.R; import cgeo.geocaching.Waypoint; import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Units; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.utils.Formatter; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import android.annotation.SuppressLint; import android.app.Activity; import android.content.res.Resources; -import android.text.format.DateUtils; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; +import android.widget.RatingBar; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; -import java.util.Date; import java.util.List; // TODO The suppression of this lint finding is bad. But to fix it, someone needs to rework the layout of the cache @@ -46,18 +44,20 @@ public final class CacheDetailsCreator { } /** - * @param nameId - * @param value - * @return the view containing the displayed string (i.e. the right side one from the pair of "label": "value") + * Create a "name: value" line. + * + * @param nameId the resource of the name field + * @param value the initial value + * @return a pair made of the whole "name: value" line (to be able to hide it for example) and of the value (to update it) */ - public TextView add(final int nameId, final CharSequence value) { + public ImmutablePair<RelativeLayout, TextView> add(final int nameId, final CharSequence value) { final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_information_item, null, false); final TextView nameView = ButterKnife.findById(layout, R.id.name); nameView.setText(res.getString(nameId)); lastValueView = ButterKnife.findById(layout, R.id.value); lastValueView.setText(value); parentView.addView(layout); - return lastValueView; + return ImmutablePair.of(layout, lastValueView); } public TextView getValueView() { @@ -72,41 +72,29 @@ public final class CacheDetailsCreator { final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_information_item, null, false); final TextView nameView = ButterKnife.findById(layout, R.id.name); lastValueView = ButterKnife.findById(layout, R.id.value); - final LinearLayout layoutStars = ButterKnife.findById(layout, R.id.stars); nameView.setText(activity.getResources().getString(nameId)); lastValueView.setText(String.format("%.1f", value) + ' ' + activity.getResources().getString(R.string.cache_rating_of) + " " + String.format("%d", max)); - createStarImages(layoutStars, value, max); + + final RatingBar layoutStars = ButterKnife.findById(layout, R.id.stars); + layoutStars.setRating(value); layoutStars.setVisibility(View.VISIBLE); parentView.addView(layout); return layout; } - private void createStarImages(final ViewGroup starsContainer, final float value, final int max) { - final LayoutInflater inflater = LayoutInflater.from(activity); - - for (int i = 0; i < max; i++) { - final ImageView star = (ImageView) inflater.inflate(R.layout.star_image, starsContainer, false); - if (value - i >= 0.75) { - star.setImageResource(R.drawable.star_on); - } else if (value - i >= 0.25) { - star.setImageResource(R.drawable.star_half); - } else { - star.setImageResource(R.drawable.star_off); - } - starsContainer.addView(star); - } - } - public void addCacheState(final Geocache cache) { if (cache.isLogOffline() || cache.isArchived() || cache.isDisabled() || cache.isPremiumMembersOnly() || cache.isFound()) { final List<String> states = new ArrayList<>(5); + String date = getVisitedDate(cache); if (cache.isLogOffline()) { - states.add(res.getString(R.string.cache_status_offline_log)); + states.add(res.getString(R.string.cache_status_offline_log) + date); + // reset the found date, to avoid showing it twice + date = ""; } if (cache.isFound()) { - states.add(res.getString(R.string.cache_status_found)); + states.add(res.getString(R.string.cache_status_found) + date); } if (cache.isArchived()) { states.add(res.getString(R.string.cache_status_archived)); @@ -121,19 +109,31 @@ public final class CacheDetailsCreator { } } + private static String getVisitedDate(final Geocache cache) { + final long visited = cache.getVisitedDate(); + return visited != 0 ? " (" + Formatter.formatShortDate(visited) + ")" : ""; + } + + private static Float distanceNonBlocking(final ICoordinates target) { + if (target.getCoords() == null) { + return null; + } + return Sensors.getInstance().currentGeo().getCoords().distanceTo(target); + } + public void addRating(final Geocache cache) { if (cache.getRating() > 0) { final RelativeLayout itemLayout = addStars(R.string.cache_rating, cache.getRating()); if (cache.getVotes() > 0) { final TextView itemAddition = ButterKnife.findById(itemLayout, R.id.addition); - itemAddition.setText("(" + cache.getVotes() + ")"); + itemAddition.setText(" (" + cache.getVotes() + ')'); itemAddition.setVisibility(View.VISIBLE); } } } public void addSize(final Geocache cache) { - if (null != cache.getSize() && cache.showSize()) { + if (cache.showSize()) { add(R.string.cache_size, cache.getSize().getL10n()); } } @@ -151,7 +151,7 @@ public final class CacheDetailsCreator { } public void addDistance(final Geocache cache, final TextView cacheDistanceView) { - Float distance = CgeoApplication.getInstance().distanceNonBlocking(cache); + Float distance = distanceNonBlocking(cache); if (distance == null) { if (cache.getDistance() != null) { distance = cache.getDistance(); @@ -170,7 +170,7 @@ public final class CacheDetailsCreator { } public void addDistance(final Waypoint wpt, final TextView waypointDistanceView) { - Float distance = CgeoApplication.getInstance().distanceNonBlocking(wpt); + final Float distance = distanceNonBlocking(wpt); String text = "--"; if (distance != null) { text = Units.getDistanceFromKilometers(distance); @@ -191,20 +191,12 @@ public final class CacheDetailsCreator { } public TextView addHiddenDate(final @NonNull Geocache cache) { - final Date hiddenDate = cache.getHiddenDate(); - if (hiddenDate == null) { + final String dateString = Formatter.formatHiddenDate(cache); + if (StringUtils.isEmpty(dateString)) { return null; } - final long time = hiddenDate.getTime(); - if (time > 0) { - String dateString = Formatter.formatFullDate(time); - if (cache.isEventCache()) { - dateString = DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString; - } - final TextView view = add(cache.isEventCache() ? R.string.cache_event : R.string.cache_hidden, dateString); - view.setId(R.id.date); - return view; - } - return null; + final TextView view = add(cache.isEventCache() ? R.string.cache_event : R.string.cache_hidden, dateString).right; + view.setId(R.id.date); + return view; } } diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index eaede2a..d9daa1d 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -3,14 +3,14 @@ package cgeo.geocaching.ui; import butterknife.InjectView; import cgeo.geocaching.CacheDetailActivity; -import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.filter.IFilter; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.sensors.GeoData; +import cgeo.geocaching.sensors.Sensors; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.sorting.CacheComparator; import cgeo.geocaching.sorting.DistanceComparator; @@ -18,7 +18,7 @@ import cgeo.geocaching.sorting.EventDateComparator; import cgeo.geocaching.sorting.InverseComparator; import cgeo.geocaching.sorting.VisitComparator; import cgeo.geocaching.utils.AngleUtils; -import cgeo.geocaching.utils.DateUtils; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.Formatter; import cgeo.geocaching.utils.Log; @@ -27,9 +27,13 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.eclipse.jdt.annotation.NonNull; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; + import android.annotation.SuppressLint; import android.app.Activity; import android.content.res.Resources; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.text.Spannable; @@ -108,9 +112,10 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { @InjectView(R.id.distance) protected DistanceView distance; @InjectView(R.id.favorite) protected TextView favorite; @InjectView(R.id.info) protected TextView info; - @InjectView(R.id.inventory) protected ImageView inventory; + @InjectView(R.id.inventory) protected TextView inventory; @InjectView(R.id.direction) protected CompassMiniView direction; @InjectView(R.id.dirimg) protected ImageView dirImg; + public Geocache cache = null; public ViewHolder(final View view) { super(view); @@ -119,10 +124,8 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { public CacheListAdapter(final Activity activity, final List<Geocache> list, final CacheListType cacheListType) { super(activity, 0, list); - final IGeoData currentGeo = CgeoApplication.getInstance().currentGeo(); - if (currentGeo != null) { - coords = currentGeo.getCoords(); - } + final GeoData currentGeo = Sensors.getInstance().currentGeo(); + coords = currentGeo.getCoords(); this.res = activity.getResources(); this.list = list; this.cacheListType = cacheListType; @@ -157,7 +160,6 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { /** * change the sort order * - * @param comparator */ public void setComparator(final CacheComparator comparator) { cacheComparator = comparator; @@ -380,6 +382,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { } else { holder = (ViewHolder) v.getTag(); } + holder.cache = cache; final boolean lightSkin = Settings.isLightSkin(); @@ -411,7 +414,7 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { } Spannable spannable = null; - if (cache.isDisabled() || cache.isArchived() || DateUtils.isPastEvent(cache)) { // strike + if (cache.isDisabled() || cache.isArchived() || CalendarUtils.isPastEvent(cache)) { // strike spannable = Spannable.Factory.getInstance().newSpannable(cache.getName()); spannable.setSpan(new StrikethroughSpan(), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -430,7 +433,9 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { } holder.text.setCompoundDrawablesWithIntrinsicBounds(getCacheIcon(cache), null, null, null); - if (cache.getInventoryItems() > 0) { + final int inventorySize = cache.getInventoryItems(); + if (inventorySize > 0) { + holder.inventory.setText(Integer.toString(inventorySize)); holder.inventory.setVisibility(View.VISIBLE); } else { holder.inventory.setVisibility(View.GONE); @@ -459,9 +464,17 @@ public class CacheListAdapter extends ArrayAdapter<Geocache> { holder.direction.updateAzimuth(azimuth); holder.direction.updateHeading(cache.getDirection()); } else if (StringUtils.isNotBlank(cache.getDirectionImg())) { - holder.dirImg.setImageDrawable(DirectionImage.getDrawable(cache.getDirectionImg())); - holder.dirImg.setVisibility(View.VISIBLE); + holder.dirImg.setVisibility(View.INVISIBLE); holder.direction.setVisibility(View.GONE); + DirectionImage.fetchDrawable(cache.getDirectionImg()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<BitmapDrawable>() { + @Override + public void call(final BitmapDrawable bitmapDrawable) { + if (cache == holder.cache) { + holder.dirImg.setImageDrawable(bitmapDrawable); + holder.dirImg.setVisibility(View.VISIBLE); + } + } + }); } else { holder.dirImg.setVisibility(View.GONE); holder.direction.setVisibility(View.GONE); diff --git a/main/src/cgeo/geocaching/ui/CompassMiniView.java b/main/src/cgeo/geocaching/ui/CompassMiniView.java index 50823fd..d50d806 100644 --- a/main/src/cgeo/geocaching/ui/CompassMiniView.java +++ b/main/src/cgeo/geocaching/ui/CompassMiniView.java @@ -1,7 +1,7 @@ package cgeo.geocaching.ui; import cgeo.geocaching.R; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.AngleUtils; @@ -50,18 +50,19 @@ final public class CompassMiniView extends View { private static final float MINIMUM_ROTATION_DEGREES_FOR_REPAINT = 5; private float azimuthRelative; - public CompassMiniView(Context context) { + public CompassMiniView(final Context context) { super(context); } - public CompassMiniView(Context context, AttributeSet attrs) { + public CompassMiniView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override public void onAttachedToWindow() { if (instances++ == 0) { - compassArrow = BitmapFactory.decodeResource(getResources(), Settings.isLightSkin() ? R.drawable.compass_arrow_mini_black : R.drawable.compass_arrow_mini_white); + final int drawable = isInEditMode() || !Settings.isLightSkin() ? R.drawable.compass_arrow_mini_white : R.drawable.compass_arrow_mini_black; + compassArrow = BitmapFactory.decodeResource(getResources(), drawable); compassArrowWidth = compassArrow.getWidth(); compassArrowHeight = compassArrow.getWidth(); } @@ -79,12 +80,12 @@ final public class CompassMiniView extends View { targetCoords = point; } - public void updateAzimuth(float azimuth) { + public void updateAzimuth(final float azimuth) { this.azimuth = azimuth; updateDirection(); } - public void updateHeading(float heading) { + public void updateHeading(final float heading) { this.heading = heading; updateDirection(); } @@ -106,7 +107,7 @@ final public class CompassMiniView extends View { azimuthRelative = AngleUtils.normalize(azimuth - heading); // avoid updates on very small changes, which are not visible to the user - float change = Math.abs(azimuthRelative - lastDrawnAzimuth); + final float change = Math.abs(azimuthRelative - lastDrawnAzimuth); if (change < MINIMUM_ROTATION_DEGREES_FOR_REPAINT) { return; } @@ -119,7 +120,7 @@ final public class CompassMiniView extends View { } @Override - protected void onDraw(Canvas canvas) { + protected void onDraw(final Canvas canvas) { super.onDraw(canvas); lastDrawnAzimuth = azimuthRelative; @@ -137,11 +138,11 @@ final public class CompassMiniView extends View { } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } - private int measureWidth(int measureSpec) { + private int measureWidth(final int measureSpec) { final int specMode = MeasureSpec.getMode(measureSpec); final int specSize = MeasureSpec.getSize(measureSpec); @@ -158,7 +159,7 @@ final public class CompassMiniView extends View { return result; } - private int measureHeight(int measureSpec) { + private int measureHeight(final int measureSpec) { final int specMode = MeasureSpec.getMode(measureSpec); final int specSize = MeasureSpec.getSize(measureSpec); diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java index 240afcf..a227770 100644 --- a/main/src/cgeo/geocaching/ui/CompassView.java +++ b/main/src/cgeo/geocaching/ui/CompassView.java @@ -81,8 +81,9 @@ public class CompassView extends View { } public void updateGraphics() { - final float newAzimuthShown = smoothUpdate(northMeasured, azimuthShown); - final float newCacheHeadingShown = smoothUpdate(cacheHeadingMeasured, cacheHeadingShown); + final float newAzimuthShown = initialDisplay ? northMeasured : smoothUpdate(northMeasured, azimuthShown); + final float newCacheHeadingShown = initialDisplay ? cacheHeadingMeasured : smoothUpdate(cacheHeadingMeasured, cacheHeadingShown); + initialDisplay = false; if (Math.abs(AngleUtils.difference(azimuthShown, newAzimuthShown)) >= 2 || Math.abs(AngleUtils.difference(cacheHeadingShown, newCacheHeadingShown)) >= 2) { azimuthShown = newAzimuthShown; @@ -151,17 +152,6 @@ public class CompassView extends View { * @param cacheHeading the cache direction (extra rotation of the needle) */ public void updateNorth(final float northHeading, final float cacheHeading) { - if (initialDisplay) { - // We will force the compass to move brutally if this is the first - // update since it is visible. - azimuthShown = northHeading; - cacheHeadingShown = cacheHeading; - - // it may take some time to get an initial direction measurement for the device - if (northHeading != 0.0) { - initialDisplay = false; - } - } northMeasured = northHeading; cacheHeadingMeasured = cacheHeading; } diff --git a/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java b/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java index 299256c..db299a2 100644 --- a/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java +++ b/main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java @@ -1,7 +1,7 @@ package cgeo.geocaching.ui; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; import android.view.View; import android.view.View.OnClickListener; @@ -13,7 +13,7 @@ import android.widget.TextView; */ public class CoordinatesFormatSwitcher implements OnClickListener { - private static GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] { + private static final GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] { GeopointFormatter.Format.LAT_LON_DECMINUTE, GeopointFormatter.Format.LAT_LON_DECSECOND, GeopointFormatter.Format.LAT_LON_DECDEGREE @@ -28,10 +28,10 @@ public class CoordinatesFormatSwitcher implements OnClickListener { } @Override - public void onClick(View view) { + public void onClick(final View view) { assert view instanceof TextView; position = (position + 1) % availableFormats.length; - TextView textView = (TextView) view; + final TextView textView = (TextView) view; // rotate coordinate formats on click textView.setText(coordinates.format(availableFormats[position])); } diff --git a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java index e2e587e..30b0e5a 100644 --- a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java +++ b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java @@ -1,40 +1,37 @@ -package cgeo.geocaching.ui;
-
-import cgeo.geocaching.utils.CryptUtils;
-
-import org.eclipse.jdt.annotation.NonNull;
-
-import android.text.Spannable;
-import android.view.View;
-import android.widget.TextView;
-
-public class DecryptTextClickListener implements View.OnClickListener {
-
- @NonNull private final TextView targetView;
-
- public DecryptTextClickListener(@NonNull final TextView targetView) {
- this.targetView = targetView;
- }
-
- @Override
- public final void onClick(final View view) {
- try {
- // do not run the click listener if a link was clicked
- if (targetView.getSelectionStart() != -1 || targetView.getSelectionEnd() != -1) {
- return;
- }
-
- CharSequence text = targetView.getText();
- if (text instanceof Spannable) {
- Spannable span = (Spannable) text;
- targetView.setText(CryptUtils.rot13(span));
- }
- else {
- String string = (String) text;
- targetView.setText(CryptUtils.rot13(string));
- }
- } catch (RuntimeException e) {
- // nothing
- }
- }
-}
+package cgeo.geocaching.ui; + +import cgeo.geocaching.utils.CryptUtils; + +import org.eclipse.jdt.annotation.NonNull; + +import android.text.Spannable; +import android.view.View; +import android.widget.TextView; + +public class DecryptTextClickListener implements View.OnClickListener { + + @NonNull private final TextView targetView; + + public DecryptTextClickListener(@NonNull final TextView targetView) { + this.targetView = targetView; + } + + @Override + public final void onClick(final View view) { + try { + // do not run the click listener if a link was clicked + if (targetView.getSelectionStart() != -1 || targetView.getSelectionEnd() != -1) { + return; + } + + final CharSequence text = targetView.getText(); + if (text instanceof Spannable) { + targetView.setText(CryptUtils.rot13((Spannable) text)); + } else { + targetView.setText(CryptUtils.rot13((String) text)); + } + } catch (final RuntimeException ignored) { + // nothing + } + } +} diff --git a/main/src/cgeo/geocaching/ui/DirectionImage.java b/main/src/cgeo/geocaching/ui/DirectionImage.java index cd7695e..e08ff51 100644 --- a/main/src/cgeo/geocaching/ui/DirectionImage.java +++ b/main/src/cgeo/geocaching/ui/DirectionImage.java @@ -3,22 +3,22 @@ package cgeo.geocaching.ui; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.network.HtmlImage; -import org.apache.commons.lang3.StringUtils; +import rx.Observable; import android.graphics.drawable.BitmapDrawable; public class DirectionImage { - static private HtmlImage htmlImage = new HtmlImage(HtmlImage.SHARED, false, StoredList.STANDARD_LIST_ID, false); + static final private HtmlImage HTML_IMAGE = new HtmlImage(HtmlImage.SHARED, false, StoredList.STANDARD_LIST_ID, false); /** * Retrieve the direction image corresponding to the direction code. * * @param directionCode one of the eight cardinal points - * @return a drawable with the arrow pointing into the right direction + * @return an observable containing zero or more drawables (the last one being the freshest image) */ - public static BitmapDrawable getDrawable(final String directionCode) { - return StringUtils.isNotBlank(directionCode) ? htmlImage.getDrawable("http://www.geocaching.com/images/icons/compass/" + directionCode + ".gif") : null; + public static Observable<BitmapDrawable> fetchDrawable(final String directionCode) { + return HTML_IMAGE.fetchDrawable("https://www.geocaching.com/images/icons/compass/" + directionCode + ".gif"); } } diff --git a/main/src/cgeo/geocaching/ui/DistanceView.java b/main/src/cgeo/geocaching/ui/DistanceView.java index a61fc4d..fb40ab4 100644 --- a/main/src/cgeo/geocaching/ui/DistanceView.java +++ b/main/src/cgeo/geocaching/ui/DistanceView.java @@ -1,7 +1,7 @@ package cgeo.geocaching.ui; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Units; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Units; import org.eclipse.jdt.annotation.NonNull; @@ -12,15 +12,15 @@ import android.widget.TextView; public class DistanceView extends TextView { private Geopoint cacheCoords = null; - public DistanceView(Context context) { + public DistanceView(final Context context) { super(context); } - public DistanceView(Context context, AttributeSet attrs) { + public DistanceView(final Context context, final AttributeSet attrs) { super(context, attrs); } - public DistanceView(Context context, AttributeSet attrs, int defStyle) { + public DistanceView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @@ -35,7 +35,7 @@ public class DistanceView extends TextView { setText(Units.getDistanceFromKilometers(coords.distanceTo(cacheCoords))); } - public void setDistance(Float distance) { + public void setDistance(final Float distance) { setText("~" + Units.getDistanceFromKilometers(distance)); } }
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/FileSelectionListAdapter.java b/main/src/cgeo/geocaching/ui/FileSelectionListAdapter.java index e07bbc3..6f7f587 100644 --- a/main/src/cgeo/geocaching/ui/FileSelectionListAdapter.java +++ b/main/src/cgeo/geocaching/ui/FileSelectionListAdapter.java @@ -40,7 +40,7 @@ public class FileSelectionListAdapter extends ArrayAdapter<File> { View v = rowView; - ViewHolder holder; + final ViewHolder holder; if (v == null) { v = inflater.inflate(R.layout.mapfile_item, parent, false); holder = new ViewHolder(v); diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java index 8bd4ac2..27a68c7 100644 --- a/main/src/cgeo/geocaching/ui/ImagesList.java +++ b/main/src/cgeo/geocaching/ui/ImagesList.java @@ -13,7 +13,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import rx.Subscription; -import rx.android.observables.AndroidObservable; +import rx.android.app.AppObservable; import rx.functions.Action0; import rx.functions.Action1; import rx.subscriptions.CompositeSubscription; @@ -102,11 +102,11 @@ public class ImagesList { imagesView = ButterKnife.findById(parentView, R.id.spoiler_list); - final HtmlImage imgGetter = new HtmlImage(geocode, true, offline ? StoredList.STANDARD_LIST_ID : StoredList.TEMPORARY_LIST_ID, false); + final HtmlImage imgGetter = new HtmlImage(geocode, true, offline ? StoredList.STANDARD_LIST_ID : StoredList.TEMPORARY_LIST.id, false); for (final Image img : images) { final LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, imagesView, false); - assert(rowView != null); + assert rowView != null; if (StringUtils.isNotBlank(img.getTitle())) { final TextView titleView = ButterKnife.findById(rowView, R.id.title); @@ -121,8 +121,8 @@ public class ImagesList { } final ImageView imageView = (ImageView) inflater.inflate(R.layout.image_item, rowView, false); - assert(imageView != null); - subscriptions.add(AndroidObservable.bindActivity(activity, imgGetter.fetchDrawable(img.getUrl())).subscribe(new Action1<BitmapDrawable>() { + assert imageView != null; + subscriptions.add(AppObservable.bindActivity(activity, imgGetter.fetchDrawable(img.getUrl())).subscribe(new Action1<BitmapDrawable>() { @Override public void call(final BitmapDrawable image) { display(imageView, image, img, rowView); @@ -203,7 +203,7 @@ public class ImagesList { } private static File saveToTemporaryJPGFile(final BitmapDrawable image) throws FileNotFoundException { - final File file = LocalStorage.getStorageFile(null, "temp.jpg", false, true); + final File file = LocalStorage.getStorageFile(HtmlImage.SHARED, "temp.jpg", false, true); BufferedOutputStream stream = null; try { stream = new BufferedOutputStream(new FileOutputStream(file)); diff --git a/main/src/cgeo/geocaching/ui/IndexOutOfBoundsAvoidingTextView.java b/main/src/cgeo/geocaching/ui/IndexOutOfBoundsAvoidingTextView.java index a0c8b52..4727bf9 100644 --- a/main/src/cgeo/geocaching/ui/IndexOutOfBoundsAvoidingTextView.java +++ b/main/src/cgeo/geocaching/ui/IndexOutOfBoundsAvoidingTextView.java @@ -12,43 +12,43 @@ import android.widget.TextView; */ public class IndexOutOfBoundsAvoidingTextView extends TextView { - public IndexOutOfBoundsAvoidingTextView(Context context, AttributeSet attrs, int defStyle) { + public IndexOutOfBoundsAvoidingTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } - public IndexOutOfBoundsAvoidingTextView(Context context, AttributeSet attrs) { + public IndexOutOfBoundsAvoidingTextView(final Context context, final AttributeSet attrs) { super(context, attrs); } - public IndexOutOfBoundsAvoidingTextView(Context context) { + public IndexOutOfBoundsAvoidingTextView(final Context context) { super(context); } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { try{ super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } catch (IndexOutOfBoundsException e) { + } catch (final IndexOutOfBoundsException ignored) { setText(getText().toString()); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } @Override - public void setGravity(int gravity){ + public void setGravity(final int gravity){ try{ super.setGravity(gravity); - } catch (IndexOutOfBoundsException e) { + } catch (final IndexOutOfBoundsException ignored) { setText(getText().toString()); super.setGravity(gravity); } } @Override - public void setText(CharSequence text, BufferType type) { + public void setText(final CharSequence text, final BufferType type) { try{ super.setText(text, type); - } catch (IndexOutOfBoundsException e) { + } catch (final IndexOutOfBoundsException ignored) { setText(text.toString()); } } diff --git a/main/src/cgeo/geocaching/ui/LoggingUI.java b/main/src/cgeo/geocaching/ui/LoggingUI.java index 8454474..e9656e8 100644 --- a/main/src/cgeo/geocaching/ui/LoggingUI.java +++ b/main/src/cgeo/geocaching/ui/LoggingUI.java @@ -17,7 +17,12 @@ import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.List; -public class LoggingUI extends AbstractUIFactory { +public final class LoggingUI extends AbstractUIFactory { + + private LoggingUI() { + // utility class + } + public static class LogTypeEntry { private final LogType logType; private final SpecialLogType specialLogType; @@ -79,7 +84,7 @@ public class LoggingUI extends AbstractUIFactory { final List<LogType> logTypes = cache.getPossibleLogTypes(); final ArrayList<LogTypeEntry> list = new ArrayList<>(); - for (LogType logType : logTypes) { + for (final LogType logType : logTypes) { list.add(new LogTypeEntry(logType, null, logType == currentLogType)); } if (cache.isLogOffline()) { @@ -94,7 +99,7 @@ public class LoggingUI extends AbstractUIFactory { builder.setAdapter(adapter, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int item) { + public void onClick(final DialogInterface dialog, final int item) { final LogTypeEntry logTypeEntry = adapter.getItem(item); if (logTypeEntry.logType == null) { switch (logTypeEntry.specialLogType) { @@ -116,7 +121,7 @@ public class LoggingUI extends AbstractUIFactory { } - public static void onPrepareOptionsMenu(Menu menu, Geocache cache) { + public static void onPrepareOptionsMenu(final Menu menu, final Geocache cache) { if (cache == null) { return; } @@ -127,7 +132,7 @@ public class LoggingUI extends AbstractUIFactory { itemOffline.setVisible(cache.supportsLogging() && Settings.getLogOffline()); } - public static void addMenuItems(Activity activity, Menu menu, Geocache cache) { + public static void addMenuItems(final Activity activity, final Menu menu, final Geocache cache) { activity.getMenuInflater().inflate(R.menu.logging_ui, menu); onPrepareOptionsMenu(menu, cache); } diff --git a/main/src/cgeo/geocaching/ui/NavigationActionProvider.java b/main/src/cgeo/geocaching/ui/NavigationActionProvider.java index 5840e27..ed4455d 100644 --- a/main/src/cgeo/geocaching/ui/NavigationActionProvider.java +++ b/main/src/cgeo/geocaching/ui/NavigationActionProvider.java @@ -9,6 +9,10 @@ import android.support.v4.view.ActionProvider; import android.view.LayoutInflater; import android.view.View; +/** + * Action provider showing the compass icon, and reacting to normal click (primary navigation) and long click (secondary + * navigation). + */ public class NavigationActionProvider extends ActionProvider { private final Context context; diff --git a/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java b/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java index acd43cb..9aa6bec 100644 --- a/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java +++ b/main/src/cgeo/geocaching/ui/OwnerActionsClickListener.java @@ -15,13 +15,13 @@ public class OwnerActionsClickListener extends AbstractUserClickListener { private final Geocache cache; - public OwnerActionsClickListener(Geocache cache) { + public OwnerActionsClickListener(final Geocache cache) { super(ConnectorFactory.getConnector(cache).getUserActions()); this.cache = cache; } @Override - protected String getUserName(View view) { + protected String getUserName(final View view) { // Use real owner name vice the one owner chose to display if (StringUtils.isNotBlank(cache.getOwnerUserId())) { return cache.getOwnerUserId(); diff --git a/main/src/cgeo/geocaching/ui/UrlPopup.java b/main/src/cgeo/geocaching/ui/UrlPopup.java index 5a8dba4..18d57d5 100644 --- a/main/src/cgeo/geocaching/ui/UrlPopup.java +++ b/main/src/cgeo/geocaching/ui/UrlPopup.java @@ -17,20 +17,20 @@ public class UrlPopup { } public void show(final String title, final String message, final String url, final String urlButtonTitle) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); + final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(message) .setIcon(android.R.drawable.ic_dialog_info) .setTitle(title) .setPositiveButton(R.string.err_none, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int id) { + public void onClick(final DialogInterface dialog, final int id) { dialog.cancel(); } }) .setNegativeButton(urlButtonTitle, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int id) { - Intent i = new Intent(Intent.ACTION_VIEW); + public void onClick(final DialogInterface dialog, final int id) { + final Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); context.startActivity(i); } diff --git a/main/src/cgeo/geocaching/ui/UserActionsClickListener.java b/main/src/cgeo/geocaching/ui/UserActionsClickListener.java index 19946bc..68c5493 100644 --- a/main/src/cgeo/geocaching/ui/UserActionsClickListener.java +++ b/main/src/cgeo/geocaching/ui/UserActionsClickListener.java @@ -12,16 +12,16 @@ import android.widget.TextView; */ public class UserActionsClickListener extends AbstractUserClickListener { - public UserActionsClickListener(Geocache cache) { + public UserActionsClickListener(final Geocache cache) { super(ConnectorFactory.getConnector(cache).getUserActions()); } - public UserActionsClickListener(Trackable trackable) { + public UserActionsClickListener(final Trackable trackable) { super(ConnectorFactory.getConnector(trackable).getUserActions()); } @Override - protected String getUserName(View view) { + protected String getUserName(final View view) { return ((TextView) view).getText().toString(); } } diff --git a/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java index d51e697..aa75db7 100644 --- a/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java +++ b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java @@ -11,7 +11,6 @@ import java.lang.ref.WeakReference; * * Create static private subclasses of this handler class in your activity. * - * @param <ActivityType> */ public abstract class WeakReferenceHandler<ActivityType extends Activity> extends Handler { diff --git a/main/src/cgeo/geocaching/ui/WrappingGridView.java b/main/src/cgeo/geocaching/ui/WrappingGridView.java new file mode 100644 index 0000000..2c85887 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/WrappingGridView.java @@ -0,0 +1,38 @@ +package cgeo.geocaching.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.GridView; + +/** + * GridView that will adjust its height to really use wrap_content. The standard GridView only shows one line of items. + * + * @see <a href="https://gist.github.com/runemart/9781609">https://gist.github.com/runemart/9781609</a> + * + */ +public class WrappingGridView extends GridView { + + public WrappingGridView(final Context context) { + super(context); + } + + public WrappingGridView(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + + public WrappingGridView(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + int heightSpec = heightMeasureSpec; + if (getLayoutParams().height == android.view.ViewGroup.LayoutParams.WRAP_CONTENT) { + // The two leftmost bits in the height measure spec have + // a special meaning, hence we can't use them to describe height. + heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); + } + super.onMeasure(widthMeasureSpec, heightSpec); + } + +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java index 9aee71a..578a15f 100644 --- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java +++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java @@ -6,11 +6,13 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.Keyboard; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.GeopointFormatter; -import cgeo.geocaching.sensors.IGeoData; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Geopoint.ParseException; +import cgeo.geocaching.location.GeopointFormatter; +import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.Settings.CoordInputFormatEnum; +import cgeo.geocaching.utils.ClipboardUtils; import cgeo.geocaching.utils.EditUtils; import org.apache.commons.lang3.StringUtils; @@ -21,6 +23,7 @@ import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.text.Editable; import android.text.TextWatcher; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -53,16 +56,14 @@ public class CoordinatesInputDialog extends DialogFragment { private static final String CACHECOORDS_ARG = "CACHECOORDS"; - public static CoordinatesInputDialog getInstance(final Geocache cache, final Geopoint gp, final IGeoData geo) { + public static CoordinatesInputDialog getInstance(final Geocache cache, final Geopoint gp, final GeoData geo) { final Bundle args = new Bundle(); if (gp != null) { args.putParcelable(GEOPOINT_ARG, gp); - } else if (geo != null && geo.getCoords() != null) { - args.putParcelable(GEOPOINT_ARG, geo.getCoords()); } else { - args.putParcelable(GEOPOINT_ARG, Geopoint.ZERO); + args.putParcelable(GEOPOINT_ARG, geo != null ? geo.getCoords() : Geopoint.ZERO); } if (geo !=null) { @@ -173,12 +174,27 @@ public class CoordinatesInputDialog extends DialogFragment { buttonCache.setVisibility(View.GONE); } + if (hasClipboardCoordinates()) { + final Button buttonClipboard = ButterKnife.findById(v, R.id.clipboard); + buttonClipboard.setOnClickListener(new ClipboardListener()); + buttonClipboard.setVisibility(View.VISIBLE); + } + final Button buttonDone = ButterKnife.findById(v, R.id.done); buttonDone.setOnClickListener(new InputDoneListener()); return v; } + @SuppressWarnings("unused") + private static boolean hasClipboardCoordinates() { + try { + new Geopoint(StringUtils.defaultString(ClipboardUtils.getText())); + } catch (final ParseException ignored) { + return false; + } + return true; + } private void updateGUI() { @@ -215,8 +231,10 @@ public class CoordinatesInputDialog extends DialogFragment { eLatDeg.setText(addZeros(gp.getLatDeg(), 2)); eLatMin.setText(addZeros(gp.getLatDegFrac(), 5)); + eLatMin.setGravity(Gravity.NO_GRAVITY); eLonDeg.setText(addZeros(gp.getLonDeg(), 3)); eLonMin.setText(addZeros(gp.getLonDegFrac(), 5)); + eLonMin.setGravity(Gravity.NO_GRAVITY); break; case Min: // DDD° MM.MMM getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE); @@ -238,9 +256,11 @@ public class CoordinatesInputDialog extends DialogFragment { eLatDeg.setText(addZeros(gp.getLatDeg(), 2)); eLatMin.setText(addZeros(gp.getLatMin(), 2)); + eLatMin.setGravity(Gravity.RIGHT); eLatSec.setText(addZeros(gp.getLatMinFrac(), 3)); eLonDeg.setText(addZeros(gp.getLonDeg(), 3)); eLonMin.setText(addZeros(gp.getLonMin(), 2)); + eLonMin.setGravity(Gravity.RIGHT); eLonSec.setText(addZeros(gp.getLonMinFrac(), 3)); break; case Sec: // DDD° MM SS.SSS @@ -263,10 +283,12 @@ public class CoordinatesInputDialog extends DialogFragment { eLatDeg.setText(addZeros(gp.getLatDeg(), 2)); eLatMin.setText(addZeros(gp.getLatMin(), 2)); + eLatMin.setGravity(Gravity.RIGHT); eLatSec.setText(addZeros(gp.getLatSec(), 2)); eLatSub.setText(addZeros(gp.getLatSecFrac(), 3)); eLonDeg.setText(addZeros(gp.getLonDeg(), 3)); eLonMin.setText(addZeros(gp.getLonMin(), 2)); + eLonMin.setGravity(Gravity.RIGHT); eLonSec.setText(addZeros(gp.getLonSec(), 2)); eLonSub.setText(addZeros(gp.getLonSecFrac(), 3)); break; @@ -391,16 +413,18 @@ public class CoordinatesInputDialog extends DialogFragment { final String lonDir = bLon.getText().toString(); final String latDeg = eLatDeg.getText().toString(); final String lonDeg = eLonDeg.getText().toString(); - final String latDegFrac = eLatMin.getText().toString(); - final String lonDegFrac = eLonMin.getText().toString(); + // right-pad decimal fraction + final String latDegFrac = padZerosRight(eLatMin.getText().toString(), 5); + final String lonDegFrac = padZerosRight(eLonMin.getText().toString(), 5); final String latMin = eLatMin.getText().toString(); final String lonMin = eLonMin.getText().toString(); final String latMinFrac = eLatSec.getText().toString(); final String lonMinFrac = eLonSec.getText().toString(); final String latSec = eLatSec.getText().toString(); final String lonSec = eLonSec.getText().toString(); - final String latSecFrac = eLatSub.getText().toString(); - final String lonSecFrac = eLonSub.getText().toString(); + // right-pad seconds fraction + final String latSecFrac = padZerosRight(eLatSub.getText().toString(), 3); + final String lonSecFrac = padZerosRight(eLonSub.getText().toString(), 3); switch (currentFormat) { case Deg: @@ -421,7 +445,7 @@ public class CoordinatesInputDialog extends DialogFragment { gp = current; return true; } - } catch (final Geopoint.ParseException e) { + } catch (final Geopoint.ParseException ignored) { // Signaled and returned below } if (signalError) { @@ -431,6 +455,10 @@ public class CoordinatesInputDialog extends DialogFragment { return false; } + private static String padZerosRight(final String value, final int len) { + return StringUtils.rightPad(value, len, '0'); + } + public int getMaxLengthFromCurrentField(final EditText editText) { if (editText == eLonDeg || editText == eLatSub || editText == eLonSub) { return 3; @@ -503,6 +531,17 @@ public class CoordinatesInputDialog extends DialogFragment { } } + private class ClipboardListener implements View.OnClickListener { + + @Override + public void onClick(final View v) { + try { + gp = new Geopoint(StringUtils.defaultString(ClipboardUtils.getText())); + updateGUI(); + } catch (final ParseException ignored) { + } + } + } private class InputDoneListener implements View.OnClickListener { diff --git a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java index 1046f81..15c9556 100644 --- a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java +++ b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java @@ -22,11 +22,11 @@ public class DateDialog extends DialogFragment { private Calendar date; public static DateDialog getInstance(final Calendar date) { - final DateDialog dd = new DateDialog(); + final DateDialog dateDialog = new DateDialog(); final Bundle args = new Bundle(); args.putSerializable("date", date); - dd.setArguments(args); - return dd; + dateDialog.setArguments(args); + return dateDialog; } @Override diff --git a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java index 21e1a82..3729677 100644 --- a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java +++ b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java @@ -25,8 +25,15 @@ import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; import android.view.ContextThemeWrapper; +import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; +import android.widget.ArrayAdapter; import android.widget.EditText; +import android.widget.ListAdapter; +import android.widget.TextView; + +import java.util.List; /** * Wrapper for {@link AlertDialog}. If you want to show a simple text, use one of the @@ -401,7 +408,6 @@ public final class Dialogs { /** * Move the cursor to the end of the input field. * - * @param input */ public static void moveCursorToEnd(final EditText input) { input.setSelection(input.getText().length(), input.getText().length()); @@ -410,4 +416,44 @@ public final class Dialogs { private static void enableDialogButtonIfNotEmpty(final AlertDialog dialog, final String input) { dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(StringUtils.isNotBlank(input)); } + + public static interface ItemWithIcon { + /** + * @return the drawable + */ + int getIcon(); + } + + public static <T extends ItemWithIcon> void select(final Activity activity, final String title, final List<T> items, final Action1<T> listener) { + final ListAdapter adapter = new ArrayAdapter<T>( + activity, + android.R.layout.select_dialog_item, + android.R.id.text1, + items) { + @Override + public View getView(final int position, final View convertView, final ViewGroup parent) { + // standard list entry + final View v = super.getView(position, convertView, parent); + + // add image + final TextView tv = (TextView) v.findViewById(android.R.id.text1); + tv.setCompoundDrawablesWithIntrinsicBounds(items.get(position).getIcon(), 0, 0, 0); + + // Add margin between image and text + final int dp5 = (int) (5 * activity.getResources().getDisplayMetrics().density + 0.5f); + tv.setCompoundDrawablePadding(dp5); + + return v; + } + }; + + new AlertDialog.Builder(activity) + .setTitle(title) + .setAdapter(adapter, new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int item) { + listener.call(items.get(item)); + } + }).show(); + } } diff --git a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java index 9858c28..d4720bf 100644 --- a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java +++ b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java @@ -15,7 +15,7 @@ import android.view.View; public class LiveMapInfoDialogBuilder { - public static AlertDialog create(Activity activity) { + public static AlertDialog create(final Activity activity) { final AlertDialog.Builder builder = new AlertDialog.Builder(activity); final Context themedContext; @@ -32,7 +32,7 @@ public class LiveMapInfoDialogBuilder { builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int which) { + public void onClick(final DialogInterface dialog, final int which) { dialog.dismiss(); CgeoApplication.getInstance().setLiveMapHintShownInThisSession(); } diff --git a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java index 7e49c97..076c412 100644 --- a/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/CacheLogsViewCreator.java @@ -2,6 +2,7 @@ package cgeo.geocaching.ui.logs; import cgeo.geocaching.CacheDetailActivity; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; @@ -24,28 +25,33 @@ import java.util.Map.Entry; public class CacheLogsViewCreator extends LogsViewCreator { private final boolean allLogs; private final Resources res = CgeoApplication.getInstance().getResources(); + private final CacheDetailActivity cacheDetailActivity; - public CacheLogsViewCreator(CacheDetailActivity cacheDetailActivity, boolean allLogs) { + public CacheLogsViewCreator(final CacheDetailActivity cacheDetailActivity, final boolean allLogs) { super(cacheDetailActivity); + this.cacheDetailActivity = cacheDetailActivity; this.allLogs = allLogs; } - /** - * May return null! - * - * @return - */ private Geocache getCache() { - if (this.activity instanceof CacheDetailActivity) { - CacheDetailActivity details = (CacheDetailActivity) this.activity; - return details.getCache(); - } - return null; + return cacheDetailActivity.getCache(); } @Override protected List<LogEntry> getLogs() { - return allLogs ? getCache().getLogs() : getCache().getFriendsLogs(); + final Geocache cache = getCache(); + final List<LogEntry> logs = allLogs ? cache.getLogs() : cache.getFriendsLogs(); + return addOwnOfflineLog(cache, logs); + } + + private List<LogEntry> addOwnOfflineLog(final Geocache cache, final List<LogEntry> logsIn) { + final LogEntry log = DataStore.loadLogOffline(cache.getGeocode()); + final ArrayList<LogEntry> logs = new ArrayList<>(logsIn); + if (log != null) { + log.author = res.getString(R.string.log_your_saved_log); + logs.add(0, log); + } + return logs; } @Override @@ -56,7 +62,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<>(logCounts.size()); for (final Entry<LogType, Integer> entry : logCounts.entrySet()) { // it may happen that the label is unknown -> then avoid any output for this type - if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null && entry.getValue() != 0) { + if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getValue() != 0) { sortedLogCounts.add(entry); } } @@ -66,7 +72,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() { @Override - public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) { + public int compare(final Entry<LogType, Integer> logCountItem1, final Entry<LogType, Integer> logCountItem2) { return logCountItem1.getKey().compareTo(logCountItem2.getKey()); } }); @@ -84,7 +90,7 @@ public class CacheLogsViewCreator extends LogsViewCreator { } @Override - protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) { + protected void fillCountOrLocation(final LogViewHolder holder, final LogEntry log) { // finds count if (log.found == -1) { holder.countOrLocation.setVisibility(View.GONE); @@ -95,6 +101,21 @@ public class CacheLogsViewCreator extends LogsViewCreator { } @Override + protected void fillViewHolder(final View convertView, final LogViewHolder holder, final LogEntry log) { + super.fillViewHolder(convertView, holder, log); + if (isOfflineLog(log)) { + holder.author.setOnClickListener(new EditOfflineLogListener(getCache(), cacheDetailActivity)); + holder.text.setOnClickListener(new EditOfflineLogListener(getCache(), cacheDetailActivity)); + holder.marker.setVisibility(View.VISIBLE); + holder.marker.setImageResource(R.drawable.mark_orange); + } + } + + private boolean isOfflineLog(final LogEntry log) { + return log.author.equals(activity.getString(R.string.log_your_saved_log)); + } + + @Override protected boolean isValid() { return getCache() != null; } diff --git a/main/src/cgeo/geocaching/ui/logs/EditOfflineLogListener.java b/main/src/cgeo/geocaching/ui/logs/EditOfflineLogListener.java new file mode 100644 index 0000000..2e0f154 --- /dev/null +++ b/main/src/cgeo/geocaching/ui/logs/EditOfflineLogListener.java @@ -0,0 +1,25 @@ +package cgeo.geocaching.ui.logs; + +import cgeo.geocaching.CacheDetailActivity; +import cgeo.geocaching.Geocache; + +import android.view.View; +import android.view.View.OnClickListener; + +class EditOfflineLogListener implements OnClickListener { + + private final Geocache cache; + private final CacheDetailActivity activity; + + public EditOfflineLogListener(final Geocache cache, final CacheDetailActivity activity) { + this.cache = cache; + this.activity = activity; + } + + @Override + public void onClick(final View v) { + activity.setNeedsRefresh(); + cache.logVisit(activity); + } + +} diff --git a/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java index 16f5537..302f86c 100644 --- a/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java +++ b/main/src/cgeo/geocaching/ui/logs/LogViewHolder.java @@ -20,7 +20,7 @@ public class LogViewHolder extends AbstractViewHolder { private int position; - public LogViewHolder(View rowView) { + public LogViewHolder(final View rowView) { super(rowView); } diff --git a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java index 23caf79..a6fd5aa 100644 --- a/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/LogsViewCreator.java @@ -4,8 +4,7 @@ import cgeo.geocaching.ImagesActivity; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActionBarActivity; -import cgeo.geocaching.list.StoredList; -import cgeo.geocaching.network.HtmlImage; +import cgeo.geocaching.network.SmileyImage; import cgeo.geocaching.ui.AbstractCachingListViewPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; import cgeo.geocaching.ui.DecryptTextClickListener; @@ -69,7 +68,7 @@ public abstract class LogsViewCreator extends AbstractCachingListViewPageViewCre return view; } - protected void fillViewHolder(final View convertView, final LogViewHolder holder, final LogEntry log) { + protected void fillViewHolder(@SuppressWarnings("unused") final View convertView, final LogViewHolder holder, final LogEntry log) { if (log.date > 0) { holder.date.setText(Formatter.formatShortDateVerbally(log.date)); holder.date.setVisibility(View.VISIBLE); @@ -87,7 +86,7 @@ public abstract class LogsViewCreator extends AbstractCachingListViewPageViewCre if (TextUtils.containsHtml(logText)) { logText = log.getDisplayText(); final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler(); - holder.text.setText(Html.fromHtml(logText, new HtmlImage(getGeocode(), false, StoredList.STANDARD_LIST_ID, false, holder.text), + holder.text.setText(Html.fromHtml(logText, new SmileyImage(getGeocode(), holder.text), unknownTagsHandler), TextView.BufferType.SPANNABLE); } else { holder.text.setText(logText, TextView.BufferType.SPANNABLE); @@ -117,12 +116,10 @@ public abstract class LogsViewCreator extends AbstractCachingListViewPageViewCre holder.marker.setVisibility(View.GONE); } - if (null == convertView) { - holder.author.setOnClickListener(createUserActionsListener()); - holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - holder.text.setOnClickListener(new DecryptTextClickListener(holder.text)); - activity.registerForContextMenu(holder.text); - } + holder.author.setOnClickListener(createUserActionsListener()); + holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); + holder.text.setOnClickListener(new DecryptTextClickListener(holder.text)); + activity.registerForContextMenu(holder.text); } abstract protected UserActionsClickListener createUserActionsListener(); diff --git a/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java index 300f510..ef8f5cc 100644 --- a/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java +++ b/main/src/cgeo/geocaching/ui/logs/TrackableLogsViewCreator.java @@ -15,14 +15,15 @@ import java.util.List; public class TrackableLogsViewCreator extends LogsViewCreator { - private final Trackable trackable; + private Trackable trackable; + private final TrackableActivity trackableActivity; /** - * @param trackableActivity */ - public TrackableLogsViewCreator(TrackableActivity trackableActivity, final Trackable trackable) { + public TrackableLogsViewCreator(final TrackableActivity trackableActivity) { super(trackableActivity); - this.trackable = trackable; + this.trackableActivity = trackableActivity; + trackable = trackableActivity.getTrackable(); } @Override @@ -32,6 +33,7 @@ public class TrackableLogsViewCreator extends LogsViewCreator { @Override protected List<LogEntry> getLogs() { + trackable = trackableActivity.getTrackable(); return trackable.getLogs(); } @@ -41,19 +43,20 @@ public class TrackableLogsViewCreator extends LogsViewCreator { } @Override - protected void fillCountOrLocation(LogViewHolder holder, final LogEntry log) { - if (StringUtils.isBlank(log.cacheName)) { - holder.countOrLocation.setVisibility(View.GONE); - } else { + protected void fillCountOrLocation(final LogViewHolder holder, final LogEntry log) { + if (StringUtils.isNotBlank(log.cacheName)) { holder.countOrLocation.setText(Html.fromHtml(log.cacheName)); + holder.countOrLocation.setVisibility(View.VISIBLE); final String cacheGuid = log.cacheGuid; final String cacheName = log.cacheName; holder.countOrLocation.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { CacheDetailActivity.startActivityGuid(activity, cacheGuid, Html.fromHtml(cacheName).toString()); } }); + } else { + holder.countOrLocation.setVisibility(View.GONE); } } diff --git a/main/src/cgeo/geocaching/utils/AngleUtils.java b/main/src/cgeo/geocaching/utils/AngleUtils.java index fdd9a9d..5ab2c75 100644 --- a/main/src/cgeo/geocaching/utils/AngleUtils.java +++ b/main/src/cgeo/geocaching/utils/AngleUtils.java @@ -1,7 +1,17 @@ package cgeo.geocaching.utils; +import cgeo.geocaching.CgeoApplication; + +import android.content.Context; +import android.view.Surface; +import android.view.WindowManager; + public final class AngleUtils { + private static class WindowManagerHolder { + public static final WindowManager WINDOW_MANAGER = (WindowManager) CgeoApplication.getInstance().getSystemService(Context.WINDOW_SERVICE); + } + private AngleUtils() { // Do not instantiate } @@ -27,4 +37,37 @@ public final class AngleUtils { public static float normalize(final float angle) { return (angle >= 0 ? angle : (360 - ((-angle) % 360))) % 360; } + + public static int getRotationOffset() { + switch (WindowManagerHolder.WINDOW_MANAGER.getDefaultDisplay().getRotation()) { + case Surface.ROTATION_90: + return 90; + case Surface.ROTATION_180: + return 180; + case Surface.ROTATION_270: + return 270; + default: + return 0; + } + } + + /** + * Take the phone rotation (through a given activity) in account and adjust the direction. + * + * @param direction the unadjusted direction in degrees, in the [0, 360[ range + * @return the adjusted direction in degrees, in the [0, 360[ range + */ + public static float getDirectionNow(final float direction) { + return normalize(direction + getRotationOffset()); + } + + /** + * Reverse the phone rotation (through a given activity) in account and adjust the direction. + * + * @param direction the unadjusted direction in degrees, in the [0, 360[ range + * @return the adjusted direction in degrees, in the [0, 360[ range + */ + public static float reverseDirectionNow(final float direction) { + return normalize(direction - getRotationOffset()); + } } diff --git a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java index 3d2b2b1..c2edd24 100644 --- a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java +++ b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java @@ -14,8 +14,6 @@ import android.os.AsyncTask; * automatically derived from the number of {@code Params} given to the task in {@link #execute(Object...)}. * </p> * - * @param <Params> - * @param <Result> */ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Params, Integer, Result> { @@ -28,9 +26,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle - * @param progressMessage */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage) { this(activity, progressTitle, progressMessage, false); @@ -39,8 +34,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle) { this(activity, progressTitle, null); @@ -49,9 +42,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle - * @param progressMessage */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage, final boolean indeterminate) { this.activity = activity; @@ -63,8 +53,6 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa /** * Creates an AsyncTask with progress dialog. * - * @param activity - * @param progressTitle */ public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final boolean indeterminate) { this(activity, progressTitle, null, indeterminate); @@ -102,6 +90,8 @@ public abstract class AsyncTaskWithProgress<Params, Result> extends AsyncTask<Pa * This method should typically be overridden by sub classes instead of {@link #onPostExecute(Object)}. * * @param result + * The result of the operation computed by {@link #doInBackground(Object...)}. + * */ protected void onPostExecuteInternal(final Result result) { // empty by default diff --git a/main/src/cgeo/geocaching/utils/BundleUtils.java b/main/src/cgeo/geocaching/utils/BundleUtils.java index 9c4255b..e61e45e 100644 --- a/main/src/cgeo/geocaching/utils/BundleUtils.java +++ b/main/src/cgeo/geocaching/utils/BundleUtils.java @@ -7,8 +7,8 @@ import android.os.Bundle; public class BundleUtils { @NonNull - public static String getString(Bundle bundle, @NonNull String key, @NonNull String defaultValue) { - String res = bundle.getString(key); + public static String getString(final Bundle bundle, @NonNull final String key, @NonNull final String defaultValue) { + final String res = bundle.getString(key); if (res != null) { return res; } diff --git a/main/src/cgeo/geocaching/utils/DateUtils.java b/main/src/cgeo/geocaching/utils/CalendarUtils.java index 9aa4222..ed3b18c 100644 --- a/main/src/cgeo/geocaching/utils/DateUtils.java +++ b/main/src/cgeo/geocaching/utils/CalendarUtils.java @@ -5,13 +5,13 @@ import cgeo.geocaching.Geocache; import java.util.Calendar; import java.util.Date; -public final class DateUtils { +public final class CalendarUtils { - private DateUtils() { + private CalendarUtils() { // utility class } - public static int daysSince(long date) { + public static int daysSince(final long date) { final Calendar logDate = Calendar.getInstance(); logDate.setTimeInMillis(date); logDate.set(Calendar.SECOND, 0); @@ -24,12 +24,27 @@ public final class DateUtils { return (int) Math.round((today.getTimeInMillis() - logDate.getTimeInMillis()) / 86400000d); } + public static int daysSince(final Calendar date) { + return daysSince(date.getTimeInMillis()); + } + public static boolean isPastEvent(final Geocache cache) { if (!cache.isEventCache()) { return false; } final Date hiddenDate = cache.getHiddenDate(); - return hiddenDate != null && DateUtils.daysSince(hiddenDate.getTime()) > 0; + return hiddenDate != null && CalendarUtils.daysSince(hiddenDate.getTime()) > 0; + } + + /** + * Return whether the given date is *more* than 1 day away. We allow 1 day to be "present time" to compensate for + * potential timezone issues. + * + * @param date + * the date + */ + public static boolean isFuture(final Calendar date) { + return daysSince(date) < -1; } } diff --git a/main/src/cgeo/geocaching/utils/CancellableHandler.java b/main/src/cgeo/geocaching/utils/CancellableHandler.java index 3ed233a..7b7aa6f 100644 --- a/main/src/cgeo/geocaching/utils/CancellableHandler.java +++ b/main/src/cgeo/geocaching/utils/CancellableHandler.java @@ -17,7 +17,7 @@ public abstract class CancellableHandler extends Handler { public static final int DONE = -1000; protected static final int UPDATE_LOAD_PROGRESS_DETAIL = 42186; private volatile boolean cancelled = false; - private static CompositeSubscription subscriptions = new CompositeSubscription(); + private final CompositeSubscription subscriptions = new CompositeSubscription(); private static class CancelHolder { final Object payload; diff --git a/main/src/cgeo/geocaching/utils/CheckerUtils.java b/main/src/cgeo/geocaching/utils/CheckerUtils.java new file mode 100644 index 0000000..39ef078 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/CheckerUtils.java @@ -0,0 +1,35 @@ +package cgeo.geocaching.utils; + +import cgeo.geocaching.Geocache; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import android.util.Patterns; + +import java.util.regex.Matcher; + +public final class CheckerUtils { + private static final String[] CHECKERS = new String[] { "geocheck.org", "geochecker.com", "certitudes.org" }; + + private CheckerUtils() { + // utility class + } + + @Nullable + public static String getCheckerUrl(@NonNull final Geocache cache) { + final String description = cache.getDescription(); + final Matcher matcher = Patterns.WEB_URL.matcher(description); + while (matcher.find()) { + final String url = matcher.group(); + for (final String checker : CHECKERS) { + if (StringUtils.containsIgnoreCase(url, checker)) { + return StringEscapeUtils.unescapeHtml4(url); + } + } + } + return null; + } +} diff --git a/main/src/cgeo/geocaching/utils/ClipboardUtils.java b/main/src/cgeo/geocaching/utils/ClipboardUtils.java index 77250f3..fb30886 100644 --- a/main/src/cgeo/geocaching/utils/ClipboardUtils.java +++ b/main/src/cgeo/geocaching/utils/ClipboardUtils.java @@ -2,6 +2,8 @@ package cgeo.geocaching.utils; import cgeo.geocaching.CgeoApplication; +import org.eclipse.jdt.annotation.Nullable; + import android.content.Context; /** @@ -9,7 +11,6 @@ import android.content.Context; * This class uses the deprecated function ClipboardManager.setText(CharSequence). * API 11 introduced setPrimaryClip(ClipData) */ -@SuppressWarnings("deprecation") public final class ClipboardUtils { private ClipboardUtils() { @@ -22,10 +23,24 @@ public final class ClipboardUtils { * @param text * The text to place in the clipboard. */ + @SuppressWarnings("deprecation") public static void copyToClipboard(final CharSequence text) { // fully qualified name used here to avoid buggy deprecation warning (of javac) on the import statement final android.text.ClipboardManager clipboard = (android.text.ClipboardManager) CgeoApplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE); clipboard.setText(text); } + /** + * get clipboard content + * + */ + @SuppressWarnings("deprecation") + @Nullable + public static String getText() { + // fully qualified name used here to avoid buggy deprecation warning (of javac) on the import statement + final android.text.ClipboardManager clipboard = (android.text.ClipboardManager) CgeoApplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE); + final CharSequence text = clipboard.getText(); + return text != null ? text.toString() : null; + } + } diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java index 815c2f4..4aec509 100644 --- a/main/src/cgeo/geocaching/utils/CryptUtils.java +++ b/main/src/cgeo/geocaching/utils/CryptUtils.java @@ -1,6 +1,5 @@ package cgeo.geocaching.utils; - import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; @@ -23,28 +22,29 @@ public final class CryptUtils { // utility class } - private static char[] base64map1 = new char[64]; - private static byte[] base64map2 = new byte[128]; + private static final byte[] EMPTY = {}; + private static final char[] BASE64MAP1 = new char[64]; + private static final byte[] BASE64MAP2 = new byte[128]; static { int i = 0; for (char c = 'A'; c <= 'Z'; c++) { - base64map1[i++] = c; + BASE64MAP1[i++] = c; } for (char c = 'a'; c <= 'z'; c++) { - base64map1[i++] = c; + BASE64MAP1[i++] = c; } for (char c = '0'; c <= '9'; c++) { - base64map1[i++] = c; + BASE64MAP1[i++] = c; } - base64map1[i++] = '+'; - base64map1[i++] = '/'; + BASE64MAP1[i++] = '+'; + BASE64MAP1[i++] = '/'; - for (i = 0; i < base64map2.length; i++) { - base64map2[i] = -1; + for (i = 0; i < BASE64MAP2.length; i++) { + BASE64MAP2[i] = -1; } for (i = 0; i < 64; i++) { - base64map2[base64map1[i]] = (byte) i; + BASE64MAP2[BASE64MAP1[i]] = (byte) i; } } @@ -58,7 +58,7 @@ public final class CryptUtils { } else if (result == ']') { plaintext = false; } else if (!plaintext) { - int capitalized = result & 32; + final int capitalized = result & 32; result &= ~capitalized; result = ((result >= 'A') && (result <= 'Z') ? ((result - 'A' + 13) % 26 + 'A') : result) | capitalized; @@ -68,50 +68,44 @@ public final class CryptUtils { } @NonNull - public static String rot13(String text) { + public static String rot13(final String text) { if (text == null) { return StringUtils.EMPTY; } final StringBuilder result = new StringBuilder(); - Rot13Encryption rot13 = new Rot13Encryption(); + final Rot13Encryption rot13 = new Rot13Encryption(); final int length = text.length(); for (int index = 0; index < length; index++) { - char c = text.charAt(index); + final char c = text.charAt(index); result.append(rot13.getNextEncryptedCharacter(c)); } return result.toString(); } - public static String md5(String text) { + public static String md5(final String text) { try { final MessageDigest digest = MessageDigest.getInstance("MD5"); digest.update(text.getBytes(CharEncoding.UTF_8), 0, text.length()); return new BigInteger(1, digest.digest()).toString(16); - } catch (NoSuchAlgorithmException e) { - Log.e("CryptUtils.md5", e); - } catch (UnsupportedEncodingException e) { + } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { Log.e("CryptUtils.md5", e); } return StringUtils.EMPTY; } - public static byte[] hashHmac(String text, String salt) { - byte[] macBytes = {}; + public static byte[] hashHmac(final String text, final String salt) { try { final SecretKeySpec secretKeySpec = new SecretKeySpec(salt.getBytes(CharEncoding.UTF_8), "HmacSHA1"); final Mac mac = Mac.getInstance("HmacSHA1"); mac.init(secretKeySpec); - macBytes = mac.doFinal(text.getBytes(CharEncoding.UTF_8)); - } catch (GeneralSecurityException e) { - Log.e("CryptUtils.hashHmac", e); - } catch (UnsupportedEncodingException e) { + return mac.doFinal(text.getBytes(CharEncoding.UTF_8)); + } catch (GeneralSecurityException | UnsupportedEncodingException e) { Log.e("CryptUtils.hashHmac", e); + return EMPTY; } - - return macBytes; } public static CharSequence rot13(final Spannable span) { @@ -119,37 +113,37 @@ public final class CryptUtils { // a SpannableStringBuilder instead of the pure text and we must replace each character inline. // Otherwise we loose all the images, colors and so on... final SpannableStringBuilder buffer = new SpannableStringBuilder(span); - Rot13Encryption rot13 = new Rot13Encryption(); + final Rot13Encryption rot13 = new Rot13Encryption(); final int length = span.length(); for (int index = 0; index < length; index++) { - char c = span.charAt(index); + final char c = span.charAt(index); buffer.replace(index, index + 1, String.valueOf(rot13.getNextEncryptedCharacter(c))); } return buffer; } - public static String base64Encode(byte[] in) { - int iLen = in.length; - int oDataLen = (iLen * 4 + 2) / 3; // output length without padding - int oLen = ((iLen + 2) / 3) * 4; // output length including padding - char[] out = new char[oLen]; + public static String base64Encode(final byte[] in) { + final int iLen = in.length; + final int oDataLen = (iLen * 4 + 2) / 3; // output length without padding + final int oLen = ((iLen + 2) / 3) * 4; // output length including padding + final char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { - int i0 = in[ip++] & 0xff; - int i1 = ip < iLen ? in[ip++] & 0xff : 0; - int i2 = ip < iLen ? in[ip++] & 0xff : 0; - int o0 = i0 >>> 2; - int o1 = ((i0 & 3) << 4) | (i1 >>> 4); - int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); - int o3 = i2 & 0x3F; - out[op++] = base64map1[o0]; - out[op++] = base64map1[o1]; - out[op] = op < oDataLen ? base64map1[o2] : '='; + final int i0 = in[ip++] & 0xff; + final int i1 = ip < iLen ? in[ip++] & 0xff : 0; + final int i2 = ip < iLen ? in[ip++] & 0xff : 0; + final int o0 = i0 >>> 2; + final int o1 = ((i0 & 3) << 4) | (i1 >>> 4); + final int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); + final int o3 = i2 & 0x3F; + out[op++] = BASE64MAP1[o0]; + out[op++] = BASE64MAP1[o1]; + out[op] = op < oDataLen ? BASE64MAP1[o2] : '='; op++; - out[op] = op < oDataLen ? base64map1[o3] : '='; + out[op] = op < oDataLen ? BASE64MAP1[o3] : '='; op++; } diff --git a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java index d8aff74..a65a9fb 100644 --- a/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java +++ b/main/src/cgeo/geocaching/utils/DatabaseBackupUtils.java @@ -6,9 +6,18 @@ import cgeo.geocaching.R; import cgeo.geocaching.ui.dialog.Dialogs; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +import rx.functions.Action0; +import rx.functions.Action1; +import rx.functions.Func0; +import rx.schedulers.Schedulers; import android.app.Activity; import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; import android.content.res.Resources; import java.io.File; @@ -21,70 +30,107 @@ public class DatabaseBackupUtils { } /** - * restore the database in a new thread, showing a progress window + * After confirming to overwrite the existing caches on the devices, restore the database in a new thread, showing a + * progress window * * @param activity * calling activity */ public static void restoreDatabase(final Activity activity) { + if (!hasBackup()) { + return; + } + final int caches = DataStore.getAllCachesCount(); + if (caches == 0) { + restoreDatabaseInternal(activity); + } + else { + Dialogs.confirm(activity, R.string.init_backup_restore, activity.getString(R.string.restore_confirm_overwrite, activity.getResources().getQuantityString(R.plurals.cache_counts, caches, caches)), new OnClickListener() { + + @Override + public void onClick(final DialogInterface dialog, final int which) { + restoreDatabaseInternal(activity); + } + }); + + } + } + + private static void restoreDatabaseInternal(final Activity activity) { final Resources res = activity.getResources(); final ProgressDialog dialog = ProgressDialog.show(activity, res.getString(R.string.init_backup_restore), res.getString(R.string.init_restore_running), true, false); final AtomicBoolean restoreSuccessful = new AtomicBoolean(false); - new Thread() { + RxUtils.andThenOnUi(Schedulers.io(), new Action0() { @Override - public void run() { + public void call() { restoreSuccessful.set(DataStore.restoreDatabaseInternal()); - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - dialog.dismiss(); - boolean restored = restoreSuccessful.get(); - String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed); - Dialogs.message(activity, R.string.init_backup_restore, message); - if (activity instanceof MainActivity) { - ((MainActivity) activity).updateCacheCounter(); - } - } - }); } - }.start(); + }, new Action0() { + @Override + public void call() { + dialog.dismiss(); + final boolean restored = restoreSuccessful.get(); + final String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed); + Dialogs.message(activity, R.string.init_backup_restore, message); + if (activity instanceof MainActivity) { + ((MainActivity) activity).updateCacheCounter(); + } + } + }); } - public static boolean createBackup(final Activity activity, final Runnable runAfterwards) { + /** + * Create a backup after confirming to overwrite the existing backup. + * + */ + public static void createBackup(final Activity activity, final Runnable runAfterwards) { // avoid overwriting an existing backup with an empty database // (can happen directly after reinstalling the app) if (DataStore.getAllCachesCount() == 0) { Dialogs.message(activity, R.string.init_backup, R.string.init_backup_unnecessary); - return false; + return; } + if (hasBackup()) { + Dialogs.confirm(activity, R.string.init_backup, activity.getString(R.string.backup_confirm_overwrite, getBackupDateTime()), new OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + createBackupInternal(activity, runAfterwards); + } + }); + } + else { + createBackupInternal(activity, runAfterwards); + } + } + + private static void createBackupInternal(final Activity activity, final Runnable runAfterwards) { final ProgressDialog dialog = ProgressDialog.show(activity, activity.getString(R.string.init_backup), activity.getString(R.string.init_backup_running), true, false); - new Thread() { + RxUtils.andThenOnUi(Schedulers.io(), new Func0<String>() { + @Override + public String call() { + return DataStore.backupDatabaseInternal(); + } + }, new Action1<String>() { @Override - public void run() { - final String backupFileName = DataStore.backupDatabaseInternal(); - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - dialog.dismiss(); - Dialogs.message(activity, - R.string.init_backup_backup, - backupFileName != null - ? activity.getString(R.string.init_backup_success) - + "\n" + backupFileName - : activity.getString(R.string.init_backup_failed)); - if (runAfterwards != null) { - runAfterwards.run(); - } - } - }); + public void call(final String backupFileName) { + dialog.dismiss(); + Dialogs.message(activity, + R.string.init_backup_backup, + backupFileName != null + ? activity.getString(R.string.init_backup_success) + + "\n" + backupFileName + : activity.getString(R.string.init_backup_failed)); + if (runAfterwards != null) { + runAfterwards.run(); + } } - }.start(); - return true; + }); } + @Nullable public static File getRestoreFile() { final File fileSourceFile = DataStore.getBackupFileInternal(); return fileSourceFile.exists() && fileSourceFile.length() > 0 ? fileSourceFile : null; @@ -94,6 +140,7 @@ public class DatabaseBackupUtils { return getRestoreFile() != null; } + @NonNull public static String getBackupDateTime() { final File restoreFile = getRestoreFile(); if (restoreFile == null) { diff --git a/main/src/cgeo/geocaching/utils/DebugUtils.java b/main/src/cgeo/geocaching/utils/DebugUtils.java index 07aac64..1f95e7c 100644 --- a/main/src/cgeo/geocaching/utils/DebugUtils.java +++ b/main/src/cgeo/geocaching/utils/DebugUtils.java @@ -22,15 +22,14 @@ public class DebugUtils { public static void createMemoryDump(final @NonNull Context context) { try { - final Date now = new Date(); final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyy-MM-dd_hh-mm", Locale.US); - File file = FileUtils.getUniqueNamedFile(Environment.getExternalStorageDirectory().getPath() - + File.separatorChar + "cgeo_dump_" + fileNameDateFormat.format(now) + ".hprof"); + final File file = FileUtils.getUniqueNamedFile(new File(Environment.getExternalStorageDirectory(), + "cgeo_dump_" + fileNameDateFormat.format(new Date()) + ".hprof")); android.os.Debug.dumpHprofData(file.getPath()); Toast.makeText(context, context.getString(R.string.init_memory_dumped, file.getAbsolutePath()), Toast.LENGTH_LONG).show(); ShareUtils.share(context, file, R.string.init_memory_dump); - } catch (IOException e) { + } catch (final IOException e) { Log.e("createMemoryDump", e); } } diff --git a/main/src/cgeo/geocaching/utils/EditUtils.java b/main/src/cgeo/geocaching/utils/EditUtils.java index 0bfe2ea..455ce4d 100644 --- a/main/src/cgeo/geocaching/utils/EditUtils.java +++ b/main/src/cgeo/geocaching/utils/EditUtils.java @@ -17,7 +17,7 @@ public final class EditUtils { editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_GO) { runnable.run(); return true; @@ -30,7 +30,7 @@ public final class EditUtils { editText.setOnKeyListener(new View.OnKeyListener() { @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { + public boolean onKey(final View v, final int keyCode, final KeyEvent event) { // If the event is a key-down event on the "enter" button if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { runnable.run(); @@ -42,7 +42,7 @@ public final class EditUtils { } - public static void disableSuggestions(EditText edit) { + public static void disableSuggestions(final EditText edit) { edit.setInputType(edit.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_FILTER); diff --git a/main/src/cgeo/geocaching/utils/FileUtils.java b/main/src/cgeo/geocaching/utils/FileUtils.java index 979820c..778b9c7 100644 --- a/main/src/cgeo/geocaching/utils/FileUtils.java +++ b/main/src/cgeo/geocaching/utils/FileUtils.java @@ -4,6 +4,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.os.Handler; import android.os.Message; @@ -23,14 +24,18 @@ import java.util.List; */ public final class FileUtils { + private static final int MAX_DIRECTORY_SCAN_DEPTH = 30; private static final String FILE_PROTOCOL = "file://"; private FileUtils() { // utility class } - public static void listDir(List<File> result, File directory, FileSelector chooser, Handler feedBackHandler) { + public static void listDir(final List<File> result, final File directory, final FileSelector chooser, final Handler feedBackHandler) { + listDirInternally(result, directory, chooser, feedBackHandler, 0); + } + private static void listDirInternally(final List<File> result, final File directory, final FileSelector chooser, final Handler feedBackHandler, final int depths) { if (directory == null || !directory.isDirectory() || !directory.canRead() || result == null || chooser == null) { @@ -40,7 +45,7 @@ public final class FileUtils { final File[] files = directory.listFiles(); if (ArrayUtils.isNotEmpty(files)) { - for (File file : files) { + for (final File file : files) { if (chooser.shouldEnd()) { return; } @@ -63,12 +68,32 @@ public final class FileUtils { feedBackHandler.sendMessage(Message.obtain(feedBackHandler, 0, name)); } - listDir(result, file, chooser, feedBackHandler); // go deeper + if (depths < MAX_DIRECTORY_SCAN_DEPTH) { + listDirInternally(result, file, chooser, feedBackHandler, depths + 1); // go deeper + } } } } } + public static boolean deleteDirectory(@NonNull final File dir) { + final File[] files = dir.listFiles(); + + // Although we are called on an existing directory, it might have been removed concurrently + // in the meantime, for example by the user or by another cleanup task. + if (files != null) { + for (final File file : files) { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + delete(file); + } + } + } + + return delete(dir); + } + public static abstract class FileSelector { public abstract boolean isSelected(File file); @@ -86,18 +111,20 @@ public final class FileUtils { * </ul> * which does not yet exist. */ - public static File getUniqueNamedFile(final String baseNameAndPath) { - String extension = StringUtils.substringAfterLast(baseNameAndPath, "."); - String pathName = StringUtils.substringBeforeLast(baseNameAndPath, "."); - int number = 1; - while (new File(getNumberedFileName(pathName, extension, number)).exists()) { - number++; + public static File getUniqueNamedFile(final File file) { + if (!file.exists()) { + return file; } - return new File(getNumberedFileName(pathName, extension, number)); - } - - private static String getNumberedFileName(String pathName, String extension, int number) { - return pathName + (number > 1 ? "_" + Integer.toString(number) : "") + "." + extension; + final String baseNameAndPath = file.getPath(); + final String prefix = StringUtils.substringBeforeLast(baseNameAndPath, ".") + "_"; + final String extension = "." + StringUtils.substringAfterLast(baseNameAndPath, "."); + for (int i = 1; i < Integer.MAX_VALUE; i++) { + final File numbered = new File(prefix + i + extension); + if (!numbered.exists()) { + return numbered; + } + } + throw new IllegalStateException("Unable to generate a non-existing file name"); } /** @@ -129,7 +156,7 @@ public final class FileUtils { * @return <code>true</code> if the directory was created, <code>false</code> on failure or if the directory already * existed. */ - public static boolean mkdirs(File file) { + public static boolean mkdirs(final File file) { final boolean success = file.mkdirs() || file.isDirectory(); // mkdirs returns false on existing directories if (!success) { Log.e("Could not make directories " + file.getAbsolutePath()); @@ -137,7 +164,7 @@ public final class FileUtils { return success; } - public static boolean writeFileUTF16(File file, String content) { + public static boolean writeFileUTF16(final File file, final String content) { // TODO: replace by some apache.commons IOUtils or FileUtils code Writer fileWriter = null; BufferedOutputStream buffer = null; @@ -177,7 +204,7 @@ public final class FileUtils { /** * Local file name when {@link #isFileUrl(String)} is <tt>true</tt>. - * + * * @return the local file */ public static File urlToFile(final String url) { diff --git a/main/src/cgeo/geocaching/utils/Formatter.java b/main/src/cgeo/geocaching/utils/Formatter.java index 3068cd4..2127d59 100644 --- a/main/src/cgeo/geocaching/utils/Formatter.java +++ b/main/src/cgeo/geocaching/utils/Formatter.java @@ -17,6 +17,7 @@ import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; public abstract class Formatter { @@ -33,7 +34,7 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatTime(long date) { + public static String formatTime(final long date) { return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_TIME); } @@ -45,7 +46,7 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatDate(long date) { + public static String formatDate(final long date) { return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE); } @@ -58,7 +59,7 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatFullDate(long date) { + public static String formatFullDate(final long date) { return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR); } @@ -71,11 +72,15 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatShortDate(long date) { - DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context); + public static String formatShortDate(final long date) { + final DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context); return dateFormat.format(date); } + private static String formatShortDateIncludingWeekday(final long time) { + return DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY) + ", " + formatShortDate(time); + } + /** * Generate a numeric date string according to system-wide settings (locale, date format) * such as "10/20/2010". Today and yesterday will be presented as strings "today" and "yesterday". @@ -84,8 +89,8 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatShortDateVerbally(long date) { - int diff = cgeo.geocaching.utils.DateUtils.daysSince(date); + public static String formatShortDateVerbally(final long date) { + final int diff = CalendarUtils.daysSince(date); switch (diff) { case 0: return CgeoApplication.getInstance().getString(R.string.log_today); @@ -104,7 +109,7 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatShortDateTime(long date) { + public static String formatShortDateTime(final long date) { return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL); } @@ -116,11 +121,11 @@ public abstract class Formatter { * milliseconds since the epoch * @return the formatted string */ - public static String formatDateTime(long date) { + public static String formatDateTime(final long date) { return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME); } - public static String formatCacheInfoLong(Geocache cache, CacheListType cacheListType) { + public static String formatCacheInfoLong(final Geocache cache, final CacheListType cacheListType) { final ArrayList<String> infos = new ArrayList<>(); if (StringUtils.isNotBlank(cache.getGeocode())) { infos.add(cache.getGeocode()); @@ -137,18 +142,18 @@ public abstract class Formatter { return StringUtils.join(infos, Formatter.SEPARATOR); } - public static String formatCacheInfoShort(Geocache cache) { + public static String formatCacheInfoShort(final Geocache cache) { final ArrayList<String> infos = new ArrayList<>(); addShortInfos(cache, infos); return StringUtils.join(infos, Formatter.SEPARATOR); } - private static void addShortInfos(Geocache cache, final ArrayList<String> infos) { + private static void addShortInfos(final Geocache cache, final ArrayList<String> infos) { if (cache.hasDifficulty()) { - infos.add("D " + String.format("%.1f", cache.getDifficulty())); + infos.add("D " + formatDT(cache.getDifficulty())); } if (cache.hasTerrain()) { - infos.add("T " + String.format("%.1f", cache.getTerrain())); + infos.add("T " + formatDT(cache.getTerrain())); } // don't show "not chosen" for events and virtuals, that should be the normal case @@ -157,12 +162,16 @@ public abstract class Formatter { } else if (cache.isEventCache()) { final Date hiddenDate = cache.getHiddenDate(); if (hiddenDate != null) { - infos.add(Formatter.formatShortDate(hiddenDate.getTime())); + infos.add(Formatter.formatShortDateIncludingWeekday(hiddenDate.getTime())); } } } - public static String formatCacheInfoHistory(Geocache cache) { + private static String formatDT(final float value) { + return String.format(Locale.getDefault(), "%.1f", value); + } + + public static String formatCacheInfoHistory(final Geocache cache) { final ArrayList<String> infos = new ArrayList<>(3); infos.add(StringUtils.upperCase(cache.getGeocode())); infos.add(Formatter.formatDate(cache.getVisitedDate())); @@ -170,9 +179,9 @@ public abstract class Formatter { return StringUtils.join(infos, Formatter.SEPARATOR); } - public static String formatWaypointInfo(Waypoint waypoint) { + public static String formatWaypointInfo(final Waypoint waypoint) { final List<String> infos = new ArrayList<>(3); - WaypointType waypointType = waypoint.getWaypointType(); + final WaypointType waypointType = waypoint.getWaypointType(); if (waypointType != WaypointType.OWN && waypointType != null) { infos.add(waypointType.getL10n()); } @@ -188,4 +197,42 @@ public abstract class Formatter { } return StringUtils.join(infos, Formatter.SEPARATOR); } + + public static String formatDaysAgo(final long date) { + final int days = CalendarUtils.daysSince(date); + switch (days) { + case 0: + return CgeoApplication.getInstance().getString(R.string.log_today); + case 1: + return CgeoApplication.getInstance().getString(R.string.log_yesterday); + default: + return CgeoApplication.getInstance().getResources().getQuantityString(R.plurals.days_ago, days, days); + } + } + + /** + * Formatting of the hidden date of a cache + * + * @return {@code null} or hidden date of the cache (or event date of the cache) in human readable format + */ + public static String formatHiddenDate(final Geocache cache) { + final Date hiddenDate = cache.getHiddenDate(); + if (hiddenDate == null) { + return null; + } + final long time = hiddenDate.getTime(); + if (time <= 0) { + return null; + } + String dateString = Formatter.formatFullDate(time); + if (cache.isEventCache()) { + dateString = DateUtils.formatDateTime(CgeoApplication.getInstance().getBaseContext(), time, DateUtils.FORMAT_SHOW_WEEKDAY) + ", " + dateString; + } + return dateString; + } + + public static String formatMapSubtitle(final Geocache cache) { + return "D " + formatDT(cache.getDifficulty()) + SEPARATOR + "T " + formatDT(cache.getTerrain()) + SEPARATOR + cache.getGeocode(); + } + } diff --git a/main/src/cgeo/geocaching/utils/HtmlUtils.java b/main/src/cgeo/geocaching/utils/HtmlUtils.java index 51c4d6e..ab6e8fe 100644 --- a/main/src/cgeo/geocaching/utils/HtmlUtils.java +++ b/main/src/cgeo/geocaching/utils/HtmlUtils.java @@ -21,10 +21,8 @@ public final class HtmlUtils { * Extract the text from a HTML based string. This is similar to what HTML.fromHtml(...) does, but this method also * removes the embedded images instead of replacing them by a small rectangular representation character. * - * @param html - * @return */ - public static String extractText(CharSequence html) { + public static String extractText(final CharSequence html) { if (StringUtils.isBlank(html)) { return StringUtils.EMPTY; } @@ -32,13 +30,13 @@ public final class HtmlUtils { // recognize images in textview HTML contents if (html instanceof Spanned) { - Spanned text = (Spanned) html; - Object[] styles = text.getSpans(0, text.length(), Object.class); - ArrayList<Pair<Integer, Integer>> removals = new ArrayList<>(); - for (Object style : styles) { + final Spanned text = (Spanned) html; + final Object[] styles = text.getSpans(0, text.length(), Object.class); + final ArrayList<Pair<Integer, Integer>> removals = new ArrayList<>(); + for (final Object style : styles) { if (style instanceof ImageSpan) { - int start = text.getSpanStart(style); - int end = text.getSpanEnd(style); + final int start = text.getSpanStart(style); + final int end = text.getSpanEnd(style); removals.add(Pair.of(start, end)); } } @@ -47,12 +45,12 @@ public final class HtmlUtils { Collections.sort(removals, new Comparator<Pair<Integer, Integer>>() { @Override - public int compare(Pair<Integer, Integer> lhs, Pair<Integer, Integer> rhs) { + public int compare(final Pair<Integer, Integer> lhs, final Pair<Integer, Integer> rhs) { return rhs.getRight().compareTo(lhs.getRight()); } }); result = text.toString(); - for (Pair<Integer, Integer> removal : removals) { + for (final Pair<Integer, Integer> removal : removals) { result = result.substring(0, removal.getLeft()) + result.substring(removal.getRight()); } } @@ -60,4 +58,15 @@ public final class HtmlUtils { // now that images are gone, do a normal html to text conversion return Html.fromHtml(result).toString().trim(); } + + public static String removeExtraParagraph(final String htmlIn) { + final String html = StringUtils.trim(htmlIn); + if (StringUtils.startsWith(html, "<p>") && StringUtils.endsWith(html, "</p>")) { + final String paragraph = StringUtils.substring(html, "<p>".length(), html.length() - "</p>".length()).trim(); + if (extractText(paragraph).equals(paragraph)) { + return paragraph; + } + } + return html; + } } diff --git a/main/src/cgeo/geocaching/utils/ImageUtils.java b/main/src/cgeo/geocaching/utils/ImageUtils.java index 739ecc4..71d5e39 100644 --- a/main/src/cgeo/geocaching/utils/ImageUtils.java +++ b/main/src/cgeo/geocaching/utils/ImageUtils.java @@ -1,16 +1,20 @@ package cgeo.geocaching.utils; import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.Image; import cgeo.geocaching.R; import cgeo.geocaching.compatibility.Compatibility; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import rx.Observable; +import rx.Scheduler.Worker; import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; import rx.functions.Action1; import android.content.res.Resources; @@ -25,6 +29,8 @@ import android.graphics.drawable.Drawable; import android.media.ExifInterface; import android.net.Uri; import android.os.Environment; +import android.text.Html; +import android.text.Html.ImageGetter; import android.util.Base64; import android.util.Base64InputStream; import android.widget.TextView; @@ -36,8 +42,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Locale; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; public final class ImageUtils { private static final int[] ORIENTATIONS = new int[] { @@ -49,6 +61,10 @@ public final class ImageUtils { private static final int[] ROTATION = new int[] { 90, 180, 270 }; private static final int MAX_DISPLAY_IMAGE_XY = 800; + // Images whose URL contains one of those patterns will not be available on the Images tab + // for opening into an external application. + private final static String[] NO_EXTERNAL = new String[] { "geocheck.org" }; + private ImageUtils() { // Do not let this class be instantiated, this is a utility class. } @@ -61,7 +77,7 @@ public final class ImageUtils { * @return BitmapDrawable The scaled image */ public static BitmapDrawable scaleBitmapToFitDisplay(@NonNull final Bitmap image) { - Point displaySize = Compatibility.getDisplaySize(); + final Point displaySize = Compatibility.getDisplaySize(); final int maxWidth = displaySize.x - 25; final int maxHeight = displaySize.y - 25; return scaleBitmapTo(image, maxWidth, maxHeight); @@ -76,7 +92,7 @@ public final class ImageUtils { */ @Nullable public static Bitmap readAndScaleImageToFitDisplay(@NonNull final String filename) { - Point displaySize = Compatibility.getDisplaySize(); + final Point displaySize = Compatibility.getDisplaySize(); // Restrict image size to 800 x 800 to prevent OOM on tablets final int maxWidth = Math.min(displaySize.x - 25, MAX_DISPLAY_IMAGE_XY); final int maxHeight = Math.min(displaySize.y - 25, MAX_DISPLAY_IMAGE_XY); @@ -128,12 +144,12 @@ public final class ImageUtils { */ public static void storeBitmap(final Bitmap bitmap, final Bitmap.CompressFormat format, final int quality, final String pathOfOutputImage) { try { - FileOutputStream out = new FileOutputStream(pathOfOutputImage); - BufferedOutputStream bos = new BufferedOutputStream(out); + final FileOutputStream out = new FileOutputStream(pathOfOutputImage); + final BufferedOutputStream bos = new BufferedOutputStream(out); bitmap.compress(format, quality, bos); bos.flush(); bos.close(); - } catch (IOException e) { + } catch (final IOException e) { Log.e("ImageHelper.storeBitmap", e); } } @@ -152,7 +168,7 @@ public final class ImageUtils { if (maxXY <= 0) { return filePath; } - Bitmap image = readDownsampledImage(filePath, maxXY, maxXY); + final Bitmap image = readDownsampledImage(filePath, maxXY, maxXY); if (image == null) { return null; } @@ -184,7 +200,7 @@ public final class ImageUtils { try { final ExifInterface exif = new ExifInterface(filePath); orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); - } catch (IOException e) { + } catch (final IOException e) { Log.e("ImageUtils.readDownsampledImage", e); } final BitmapFactory.Options sizeOnlyOptions = new BitmapFactory.Options(); @@ -233,7 +249,7 @@ public final class ImageUtils { } // Create a media file name - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()); + final String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()); return new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); } @@ -254,7 +270,7 @@ public final class ImageUtils { * @return <tt>true</tt> if the URL contains at least one of the patterns, <tt>false</tt> otherwise */ public static boolean containsPattern(final String url, final String[] patterns) { - for (String entry : patterns) { + for (final String entry : patterns) { if (StringUtils.containsIgnoreCase(url, entry)) { return true; } @@ -282,7 +298,7 @@ public final class ImageUtils { /** * Decode a base64-encoded string and save the result into a stream. - * + * * @param inString * the encoded string * @param out @@ -303,42 +319,158 @@ public final class ImageUtils { } /** + * Add images present in the HTML description to the existing collection. + * @param images a collection of images + * @param geocode the common title for images in the description + * @param htmlText the HTML description to be parsed, can be repeated + */ + public static void addImagesFromHtml(final Collection<Image> images, final String geocode, final String... htmlText) { + final Set<String> urls = new LinkedHashSet<>(); + for (final Image image : images) { + urls.add(image.getUrl()); + } + for (final String text: htmlText) { + Html.fromHtml(StringUtils.defaultString(text), new ImageGetter() { + @Override + public Drawable getDrawable(final String source) { + if (!urls.contains(source) && canBeOpenedExternally(source)) { + images.add(new Image(source, StringUtils.defaultString(geocode))); + urls.add(source); + } + return null; + } + }, null); + } + } + + /** * Container which can hold a drawable (initially an empty one) and get a newer version when it * becomes available. It also invalidates the view the container belongs to, so that it is * redrawn properly. + * <p/> + * When a new version of the drawable is available, it is put into a queue and, if needed (no other elements + * waiting in the queue), a refresh is launched on the UI thread. This refresh will empty the queue (including + * elements arrived in the meantime) and ensures that the view is uploaded only once all the queued requests have + * been handled. */ - @SuppressWarnings("deprecation") - public final static class ContainerDrawable extends BitmapDrawable implements Action1<Drawable> { + public static class ContainerDrawable extends BitmapDrawable implements Action1<Drawable> { + final private static Object lock = new Object(); // Used to lock the queue to determine if a refresh needs to be scheduled + final private static LinkedBlockingQueue<ImmutablePair<ContainerDrawable, Drawable>> REDRAW_QUEUE = new LinkedBlockingQueue<>(); + final private static Set<TextView> VIEWS = new HashSet<>(); // Modified only on the UI thread + final private static Worker UI_WORKER = AndroidSchedulers.mainThread().createWorker(); + final private static Action0 REDRAW_QUEUED_DRAWABLES = new Action0() { + @Override + public void call() { + redrawQueuedDrawables(); + } + }; + private Drawable drawable; - final private TextView view; + final protected TextView view; - public ContainerDrawable(@NonNull final TextView view) { + @SuppressWarnings("deprecation") + public ContainerDrawable(@NonNull final TextView view, final Observable<? extends Drawable> drawableObservable) { this.view = view; drawable = null; setBounds(0, 0, 0, 0); - } - - public ContainerDrawable(@NonNull final TextView view, final Observable<? extends Drawable> drawableObservable) { - this(view); - updateFrom(drawableObservable); + drawableObservable.subscribe(this); } @Override - public void draw(final Canvas canvas) { + public final void draw(final Canvas canvas) { if (drawable != null) { drawable.draw(canvas); } } @Override - public void call(final Drawable newDrawable) { + public final void call(final Drawable newDrawable) { + final boolean needsRedraw; + synchronized (lock) { + // Check for emptyness inside the call to match the behaviour in redrawQueuedDrawables(). + needsRedraw = REDRAW_QUEUE.isEmpty(); + REDRAW_QUEUE.add(ImmutablePair.of(this, newDrawable)); + } + if (needsRedraw) { + UI_WORKER.schedule(REDRAW_QUEUED_DRAWABLES); + } + } + + /** + * Update the container with the new drawable. Called on the UI thread. + * + * @param newDrawable the new drawable + * @return the view to update + */ + protected TextView updateDrawable(final Drawable newDrawable) { setBounds(0, 0, newDrawable.getIntrinsicWidth(), newDrawable.getIntrinsicHeight()); drawable = newDrawable; - view.setText(view.getText()); + return view; + } + + private static void redrawQueuedDrawables() { + if (!REDRAW_QUEUE.isEmpty()) { + // Add a small margin so that drawables arriving between the beginning of the allocation and the draining + // of the queue might be absorbed without reallocation. + final ArrayList<ImmutablePair<ContainerDrawable, Drawable>> toRedraw = new ArrayList<>(REDRAW_QUEUE.size() + 16); + synchronized (lock) { + // Empty the queue inside the lock to match the check done in call(). + REDRAW_QUEUE.drainTo(toRedraw); + } + for (final ImmutablePair<ContainerDrawable, Drawable> redrawable : toRedraw) { + VIEWS.add(redrawable.left.updateDrawable(redrawable.right)); + } + for (final TextView view : VIEWS) { + view.setText(view.getText()); + } + VIEWS.clear(); + } + } + + } + + /** + * Image that automatically scales to fit a line of text in the containing {@link TextView}. + */ + public final static class LineHeightContainerDrawable extends ContainerDrawable { + public LineHeightContainerDrawable(@NonNull final TextView view, final Observable<? extends Drawable> drawableObservable) { + super(view, drawableObservable); } - public void updateFrom(final Observable<? extends Drawable> drawableObservable) { - drawableObservable.observeOn(AndroidSchedulers.mainThread()).subscribe(this); + @Override + protected TextView updateDrawable(final Drawable newDrawable) { + super.updateDrawable(newDrawable); + setBounds(ImageUtils.scaleImageToLineHeight(newDrawable, view)); + return view; } } + + public static boolean canBeOpenedExternally(final String source) { + return !containsPattern(source, NO_EXTERNAL); + } + + public static Rect scaleImageToLineHeight(final Drawable drawable, final TextView view) { + final int lineHeight = (int) (view.getLineHeight() * 0.8); + final int width = drawable.getIntrinsicWidth() * lineHeight / drawable.getIntrinsicHeight(); + return new Rect(0, 0, width, lineHeight); + } + + public static Bitmap convertToBitmap(final Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + // handle solid colors, which have no width + int width = drawable.getIntrinsicWidth(); + width = width > 0 ? width : 1; + int height = drawable.getIntrinsicHeight(); + height = height > 0 ? height : 1; + + final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } } diff --git a/main/src/cgeo/geocaching/utils/JsonUtils.java b/main/src/cgeo/geocaching/utils/JsonUtils.java new file mode 100644 index 0000000..492e137 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/JsonUtils.java @@ -0,0 +1,20 @@ +package cgeo.geocaching.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; + +public class JsonUtils { + + private static final ObjectMapper mapper = new ObjectMapper(); + public static final ObjectReader reader = mapper.reader(); + public static final ObjectWriter writer = mapper.writer(); + + public static final JsonNodeFactory factory = new JsonNodeFactory(true); + + private JsonUtils() { + // Do not instantiate + } + +} diff --git a/main/src/cgeo/geocaching/utils/LazyInitializedList.java b/main/src/cgeo/geocaching/utils/LazyInitializedList.java index b0e2e46..866acad 100644 --- a/main/src/cgeo/geocaching/utils/LazyInitializedList.java +++ b/main/src/cgeo/geocaching/utils/LazyInitializedList.java @@ -49,7 +49,7 @@ public abstract class LazyInitializedList<ElementType> extends AbstractList<Elem } @Override - public void add(int index, final ElementType element) { + public void add(final int index, final ElementType element) { getUnderlyingList().add(index, element); } diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java index 6122532..aecfaf1 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java @@ -30,7 +30,7 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { final int initialCapacity; final float loadFactor; - protected LeastRecentlyUsedMap(int maxEntries, int initialCapacity, float loadFactor, OperationModes opMode) { + protected LeastRecentlyUsedMap(final int maxEntries, final int initialCapacity, final float loadFactor, final OperationModes opMode) { super(initialCapacity, loadFactor, (opMode==OperationModes.LRU_CACHE)); this.initialCapacity = initialCapacity; this.loadFactor = loadFactor; @@ -38,12 +38,12 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { this.opMode = opMode; } - protected LeastRecentlyUsedMap(int maxEntries, OperationModes opMode) { + protected LeastRecentlyUsedMap(final int maxEntries, final OperationModes opMode) { this(maxEntries, 16, 0.75f, opMode); } @Override - public V put(K key, V value) { + public V put(final K key, final V value) { // in case the underlying Map is not running with accessOrder==true, the map won't notice any changes // of existing keys, so for the normal BOUNDED mode we remove and put the value to get its order updated. if (opMode == OperationModes.BOUNDED && containsKey(key)) { @@ -57,7 +57,7 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { } @Override - protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { + protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) { return size() > maxEntries; } @@ -66,9 +66,9 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { } @Override - public V remove(Object key) { + public V remove(final Object key) { - V removed = super.remove(key); + final V removed = super.remove(key); if (removed != null && removeHandler != null) { removeHandler.onRemove(removed); @@ -84,18 +84,18 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { * @param removeHandler * The new handler to receive notifications or null to remove a handler */ - public void setRemoveHandler(RemoveHandler<V> removeHandler) { + public void setRemoveHandler(final RemoveHandler<V> removeHandler) { this.removeHandler = removeHandler; } public static class LruCache<K, V> extends LeastRecentlyUsedMap<K, V> { private static final long serialVersionUID = 9028478916221334454L; - public LruCache(int maxEntries, int initialCapacity, float loadFactor) { + public LruCache(final int maxEntries, final int initialCapacity, final float loadFactor) { super(maxEntries, initialCapacity, loadFactor, OperationModes.LRU_CACHE); } - public LruCache(int maxEntries) { + public LruCache(final int maxEntries) { super(maxEntries, OperationModes.LRU_CACHE); } } @@ -104,11 +104,11 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { private static final long serialVersionUID = -1476389304214398315L; - public Bounded(int maxEntries, int initialCapacity, float loadFactor) { + public Bounded(final int maxEntries, final int initialCapacity, final float loadFactor) { super(maxEntries, initialCapacity, loadFactor, OperationModes.BOUNDED); } - public Bounded(int maxEntries) { + public Bounded(final int maxEntries) { super(maxEntries, OperationModes.BOUNDED); } } @@ -117,7 +117,6 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { * Interface for handlers that wish to get notified when items are * removed from the LRUMap * - * @param <V> */ public interface RemoveHandler<V> { diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java index a69f427..c139136 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java @@ -20,21 +20,18 @@ import java.util.List; * access has to be guarded externally or the synchronized getAsList method can be used * to get a clone for iteration. */ -public class LeastRecentlyUsedSet<E> extends AbstractSet<E> - implements Cloneable, java.io.Serializable { +public class LeastRecentlyUsedSet<E> extends AbstractSet<E> { - private static final long serialVersionUID = -1942301031191419547L; - - private transient LeastRecentlyUsedMap<E, Object> map; + private final LeastRecentlyUsedMap<E, Object> map; private static final Object PRESENT = new Object(); - public LeastRecentlyUsedSet(int maxEntries, int initialCapacity, float loadFactor) { + public LeastRecentlyUsedSet(final int maxEntries, final int initialCapacity, final float loadFactor) { // because we don't use any Map.get() methods from the Set, BOUNDED and LRU_CACHE have the exact same Behaviour // So we use LRU_CACHE mode because it should perform a bit better (as it doesn't re-add explicitly) map = new LeastRecentlyUsedMap.LruCache<>(maxEntries, initialCapacity, loadFactor); } - public LeastRecentlyUsedSet(int maxEntries) { + public LeastRecentlyUsedSet(final int maxEntries) { map = new LeastRecentlyUsedMap.LruCache<>(maxEntries); } @@ -79,7 +76,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> * @see HashSet */ @Override - public synchronized boolean contains(Object o) { + public synchronized boolean contains(final Object o) { return map.containsKey(o); } @@ -90,7 +87,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> * @see HashSet */ @Override - public synchronized boolean add(E e) { + public synchronized boolean add(final E e) { if (e == null) { throw new IllegalArgumentException("LeastRecentlyUsedSet cannot take null element"); } @@ -104,7 +101,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> * @see HashSet */ @Override - public synchronized boolean remove(Object o) { + public synchronized boolean remove(final Object o) { return map.remove(o) == PRESENT; } @@ -132,26 +129,6 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> } /** - * (synchronized) Clone of the set - * Copy of the HashSet code if clone() - * - * @see HashSet - */ - @Override - @SuppressWarnings("unchecked") - public Object clone() throws CloneNotSupportedException { - try { - synchronized (this) { - final LeastRecentlyUsedSet<E> newSet = (LeastRecentlyUsedSet<E>) super.clone(); - newSet.map = (LeastRecentlyUsedMap<E, Object>) map.clone(); - return newSet; - } - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } - - /** * Creates a clone as a list in a synchronized fashion. * * @return List based clone of the set @@ -160,56 +137,4 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E> return new ArrayList<>(this); } - /** - * Serialization version of HashSet with the additional parameters for the custom Map - * - * @see HashSet - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - // Write out any hidden serialization magic - s.defaultWriteObject(); - - // Write out HashMap capacity and load factor - s.writeInt(map.initialCapacity); - s.writeFloat(map.loadFactor); - s.writeInt(map.getMaxEntries()); - - // Write out size - s.writeInt(map.size()); - - // Write out all elements in the proper order. - for (final E e : map.keySet()) { - s.writeObject(e); - } - } - - /** - * Serialization version of HashSet with the additional parameters for the custom Map - * - * @see HashSet - */ - @SuppressWarnings("unchecked") - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in any hidden serialization magic - s.defaultReadObject(); - - // Read in HashMap capacity and load factor and create backing HashMap - final int capacity = s.readInt(); - final float loadFactor = s.readFloat(); - final int maxEntries = s.readInt(); - - map = new LeastRecentlyUsedMap.LruCache<>(maxEntries, capacity, loadFactor); - - // Read in size - final int size = s.readInt(); - - // Read in all elements in the proper order. - for (int i = 0; i < size; i++) { - E e = (E) s.readObject(); - map.put(e, PRESENT); - } - } - } diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java index f338a8e..861faaa 100644 --- a/main/src/cgeo/geocaching/utils/Log.java +++ b/main/src/cgeo/geocaching/utils/Log.java @@ -37,62 +37,65 @@ public final class Log { /** * Save a copy of the debug flag from the settings for performance reasons. * - * @param isDebug */ public static void setDebug(final boolean isDebug) { Log.isDebug = isDebug; } + private static String addThreadInfo(final String msg) { + return new StringBuilder("[").append(Thread.currentThread().getName()).append("] ").append(msg).toString(); + } + public static void v(final String msg) { if (isDebug) { - android.util.Log.v(TAG, msg); + android.util.Log.v(TAG, addThreadInfo(msg)); } } public static void v(final String msg, final Throwable t) { if (isDebug) { - android.util.Log.v(TAG, msg, t); + android.util.Log.v(TAG, addThreadInfo(msg), t); } } public static void d(final String msg) { if (isDebug) { - android.util.Log.d(TAG, msg); + android.util.Log.d(TAG, addThreadInfo(msg)); } } public static void d(final String msg, final Throwable t) { if (isDebug) { - android.util.Log.d(TAG, msg, t); + android.util.Log.d(TAG, addThreadInfo(msg), t); } } public static void i(final String msg) { if (isDebug) { - android.util.Log.i(TAG, msg); + android.util.Log.i(TAG, addThreadInfo(msg)); } } public static void i(final String msg, final Throwable t) { if (isDebug) { - android.util.Log.i(TAG, msg, t); + android.util.Log.i(TAG, addThreadInfo(msg), t); } } public static void w(final String msg) { - android.util.Log.w(TAG, msg); + android.util.Log.w(TAG, addThreadInfo(msg)); } public static void w(final String msg, final Throwable t) { - android.util.Log.w(TAG, msg, t); + android.util.Log.w(TAG, addThreadInfo(msg), t); } public static void e(final String msg) { - android.util.Log.e(TAG, msg); + android.util.Log.e(TAG, addThreadInfo(msg)); } public static void e(final String msg, final Throwable t) { - android.util.Log.e(TAG, msg, t); + android.util.Log.e(TAG, addThreadInfo(msg), t); } /** @@ -116,7 +119,7 @@ public final class Log { Writer writer = null; try { writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), CharEncoding.UTF_8)); - writer.write(msg); + writer.write(addThreadInfo(msg)); } catch (final IOException e) { Log.e("logToFile: cannot write to " + file, e); } finally { diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index ff4013c..1db3d5b 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -215,7 +215,7 @@ public final class LogTemplateProvider { } final Geocache cache = context.getCache(); if (cache != null) { - return cache.getUrl(); + return StringUtils.defaultString(cache.getUrl()); } return StringUtils.EMPTY; } diff --git a/main/src/cgeo/geocaching/utils/MapUtils.java b/main/src/cgeo/geocaching/utils/MapUtils.java index 5120ca5..f41247c 100644 --- a/main/src/cgeo/geocaching/utils/MapUtils.java +++ b/main/src/cgeo/geocaching/utils/MapUtils.java @@ -154,7 +154,6 @@ public final class MapUtils { } private static int calculateResolution(final Drawable marker) { - final int resolution = marker.getIntrinsicWidth() > 40 ? (marker.getIntrinsicWidth() > 50 ? (marker.getIntrinsicWidth() > 70 ? (marker.getIntrinsicWidth() > 100 ? 4 : 3) : 2) : 1) : 0; - return resolution; + return marker.getIntrinsicWidth() > 40 ? (marker.getIntrinsicWidth() > 50 ? (marker.getIntrinsicWidth() > 70 ? (marker.getIntrinsicWidth() > 100 ? 4 : 3) : 2) : 1) : 0; } } diff --git a/main/src/cgeo/geocaching/utils/MatcherWrapper.java b/main/src/cgeo/geocaching/utils/MatcherWrapper.java index c99d3c4..733a18e 100644 --- a/main/src/cgeo/geocaching/utils/MatcherWrapper.java +++ b/main/src/cgeo/geocaching/utils/MatcherWrapper.java @@ -2,6 +2,8 @@ package cgeo.geocaching.utils; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.eclipse.jdt.annotation.NonNull; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -13,7 +15,7 @@ import java.util.regex.Pattern; public class MatcherWrapper { private final Matcher matcher; - public MatcherWrapper(Pattern pattern, String input) { + public MatcherWrapper(@NonNull final Pattern pattern, @NonNull final String input) { this.matcher = pattern.matcher(input); } @@ -24,14 +26,14 @@ public class MatcherWrapper { return matcher.find(); } - public boolean find(int start) { + public boolean find(final int start) { return matcher.find(start); } /** * see {@link Matcher#group(int)} */ - public String group(int index) { + public String group(final int index) { return newString(matcher.group(index)); } @@ -43,11 +45,9 @@ public class MatcherWrapper { * <p> * Do not change this method, even if Findbugs and other tools will report a violation for that line! * - * @param input - * @return */ @SuppressFBWarnings("DM_STRING_CTOR") - private static String newString(String input) { + private static String newString(final String input) { if (input == null) { return null; } @@ -78,7 +78,7 @@ public class MatcherWrapper { /** * see {@link Matcher#replaceAll(String)} */ - public String replaceAll(String replacement) { + public String replaceAll(final String replacement) { return newString(matcher.replaceAll(replacement)); } @@ -92,7 +92,7 @@ public class MatcherWrapper { /** * see {@link Matcher#replaceFirst(String)} */ - public String replaceFirst(String replacement) { + public String replaceFirst(final String replacement) { return newString(matcher.replaceFirst(replacement)); } } diff --git a/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java b/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java index 1401542..0c6365c 100644 --- a/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java +++ b/main/src/cgeo/geocaching/utils/OOMDumpingUncaughtExceptionHandler.java @@ -11,14 +11,12 @@ public class OOMDumpingUncaughtExceptionHandler implements UncaughtExceptionHand private boolean defaultReplaced = false; public static boolean activateHandler() { - final OOMDumpingUncaughtExceptionHandler handler = new OOMDumpingUncaughtExceptionHandler(); return handler.activate(); } private boolean activate() { - defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); // replace default handler if that has not been done already @@ -34,10 +32,8 @@ public class OOMDumpingUncaughtExceptionHandler implements UncaughtExceptionHand } public static boolean resetToDefault() { - - boolean defaultResetted = false; - final UncaughtExceptionHandler unspecificHandler = Thread.getDefaultUncaughtExceptionHandler(); + boolean defaultResetted = unspecificHandler != null; if (unspecificHandler instanceof OOMDumpingUncaughtExceptionHandler) { final OOMDumpingUncaughtExceptionHandler handler = (OOMDumpingUncaughtExceptionHandler) unspecificHandler; @@ -48,7 +44,6 @@ public class OOMDumpingUncaughtExceptionHandler implements UncaughtExceptionHand } private boolean reset() { - final boolean resetted = defaultReplaced; if (defaultReplaced) { diff --git a/main/src/cgeo/geocaching/utils/ProcessUtils.java b/main/src/cgeo/geocaching/utils/ProcessUtils.java index d80674b..6a57cbf 100644 --- a/main/src/cgeo/geocaching/utils/ProcessUtils.java +++ b/main/src/cgeo/geocaching/utils/ProcessUtils.java @@ -3,7 +3,10 @@ package cgeo.geocaching.utils; import cgeo.geocaching.CgeoApplication; import org.apache.commons.collections4.CollectionUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import android.app.Activity; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -21,10 +24,8 @@ public final class ProcessUtils { /** * Preferred method to detect the availability of an external app * - * @param packageName - * @return */ - public static boolean isLaunchable(final String packageName) { + public static boolean isLaunchable(@Nullable final String packageName) { return getLaunchIntent(packageName) != null; } @@ -33,17 +34,15 @@ public final class ProcessUtils { * This function is relatively costly, so if you know that the package in question has * a launch intent, use isLaunchable() instead. * - * @param packageName - * @return */ - public static boolean isInstalled(final String packageName) { + public static boolean isInstalled(@NonNull final String packageName) { return isLaunchable(packageName) || hasPackageInstalled(packageName); } /** * This will find installed applications even without launch intent (e.g. the streetview plugin). */ - private static boolean hasPackageInstalled(final String packageName) { + private static boolean hasPackageInstalled(@NonNull final String packageName) { final List<PackageInfo> packs = CgeoApplication.getInstance().getPackageManager().getInstalledPackages(0); for (final PackageInfo packageInfo : packs) { if (packageName.equals(packageInfo.packageName)) { @@ -56,7 +55,8 @@ public final class ProcessUtils { /** * This will find applications, which can be launched. */ - public static Intent getLaunchIntent(final String packageName) { + @Nullable + public static Intent getLaunchIntent(@Nullable final String packageName) { if (packageName == null) { return null; } @@ -65,12 +65,12 @@ public final class ProcessUtils { // This can throw an exception where the exception type is only defined on API Level > 3 // therefore surround with try-catch return packageManager.getLaunchIntentForPackage(packageName); - } catch (final Exception e) { + } catch (final Exception ignored) { return null; } } - public static boolean isIntentAvailable(final String intent) { + public static boolean isIntentAvailable(@NonNull final String intent) { return isIntentAvailable(intent, null); } @@ -79,16 +79,16 @@ public final class ProcessUtils { * method queries the package manager for installed packages that can * respond to an intent with the specified action. If no suitable package is * found, this method returns false. - * + * * @param action * The Intent action to check for availability. * @param uri * The Intent URI to check for availability. - * + * * @return True if an Intent with the specified action can be sent and * responded to, false otherwise. */ - public static boolean isIntentAvailable(final String action, final Uri uri) { + public static boolean isIntentAvailable(@NonNull final String action, @Nullable final Uri uri) { final PackageManager packageManager = CgeoApplication.getInstance().getPackageManager(); final Intent intent; if (uri == null) { @@ -98,7 +98,23 @@ public final class ProcessUtils { } final List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); - return CollectionUtils.isNotEmpty(list); + final List<ResolveInfo> servicesList = packageManager.queryIntentServices(intent, + PackageManager.MATCH_DEFAULT_ONLY); + return CollectionUtils.isNotEmpty(list) || CollectionUtils.isNotEmpty(servicesList); + } + + @SuppressWarnings("deprecation") + public static void openMarket(final Activity activity, @NonNull final String packageName) { + try { + final String url = "market://details?id=" + packageName; + final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activity.startActivity(marketIntent); + + } catch (final RuntimeException ignored) { + // market not available, fall back to browser + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + packageName))); + } } } diff --git a/main/src/cgeo/geocaching/utils/RxUtils.java b/main/src/cgeo/geocaching/utils/RxUtils.java index 241ba78..08cc3e7 100644 --- a/main/src/cgeo/geocaching/utils/RxUtils.java +++ b/main/src/cgeo/geocaching/utils/RxUtils.java @@ -1,22 +1,56 @@ package cgeo.geocaching.utils; import rx.Observable; +import rx.Observable.OnSubscribe; import rx.Scheduler; +import rx.Scheduler.Worker; +import rx.Subscriber; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; +import rx.functions.Action1; +import rx.functions.Func0; +import rx.functions.Func1; +import rx.internal.util.RxThreadFactory; import rx.observables.BlockingObservable; +import rx.observers.Subscribers; import rx.schedulers.Schedulers; +import rx.subjects.PublishSubject; +import rx.subscriptions.Subscriptions; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Process; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; public class RxUtils { - // Utility class, not to be instanciated - private RxUtils() {} + private RxUtils() { + // Utility class, not to be instantiated + } public final static Scheduler computationScheduler = Schedulers.computation(); - public static final Scheduler networkScheduler = Schedulers.from(new ThreadPoolExecutor(10, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())); + public static final Scheduler networkScheduler = Schedulers.from(Executors.newFixedThreadPool(10, new RxThreadFactory("network-"))); + + public static final Scheduler refreshScheduler = Schedulers.from(Executors.newFixedThreadPool(3, new RxThreadFactory("refresh-"))); + + private static final HandlerThread looperCallbacksThread = + new HandlerThread("looper callbacks", Process.THREAD_PRIORITY_DEFAULT); + + static { + looperCallbacksThread.start(); + } + + public static final Looper looperCallbacksLooper = looperCallbacksThread.getLooper(); + public static final Scheduler looperCallbacksScheduler = AndroidSchedulers.handlerThread(new Handler(looperCallbacksLooper)); + public static final Worker looperCallbacksWorker = looperCallbacksScheduler.createWorker(); public static <T> void waitForCompletion(final BlockingObservable<T> observable) { observable.lastOrDefault(null); @@ -25,4 +59,139 @@ public class RxUtils { public static void waitForCompletion(final Observable<?>... observables) { waitForCompletion(Observable.merge(observables).toBlocking()); } + + /** + * Subscribe function whose subscription and unsubscription take place on a looper thread. + * + * @param <T> + * the type of the observable + */ + public static abstract class LooperCallbacks<T> implements OnSubscribe<T> { + + final AtomicInteger counter = new AtomicInteger(0); + final long stopDelay; + final TimeUnit stopDelayUnit; + final protected PublishSubject<T> subject = PublishSubject.create(); + + public LooperCallbacks(final long stopDelay, final TimeUnit stopDelayUnit) { + this.stopDelay = stopDelay; + this.stopDelayUnit = stopDelayUnit; + } + + public LooperCallbacks() { + this(0, TimeUnit.SECONDS); + } + + @Override + final public void call(final Subscriber<? super T> subscriber) { + subscriber.add(subject.subscribe(Subscribers.from(subscriber))); + looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (counter.getAndIncrement() == 0) { + onStart(); + } + subscriber.add(Subscriptions.create(new Action0() { + @Override + public void call() { + looperCallbacksWorker.schedule(new Action0() { + @Override + public void call() { + if (counter.decrementAndGet() == 0) { + onStop(); + } + } + }, stopDelay, stopDelayUnit); + } + })); + } + }); + } + + abstract protected void onStart(); + + abstract protected void onStop(); + } + + public static<T> Observable<T> rememberLast(final Observable<T> observable, final T initialValue) { + final AtomicReference<T> lastValue = new AtomicReference<>(initialValue); + return observable.doOnNext(new Action1<T>() { + @Override + public void call(final T value) { + lastValue.set(value); + } + }).startWith(Observable.defer(new Func0<Observable<T>>() { + @Override + public Observable<T> call() { + final T last = lastValue.get(); + return last != null ? Observable.just(last) : Observable.<T>empty(); + } + })).replay(1).refCount(); + } + + public static <T> void andThenOnUi(final Scheduler scheduler, final Func0<T> background, final Action1<T> foreground) { + scheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + final T value = background.call(); + AndroidSchedulers.mainThread().createWorker().schedule(new Action0() { + @Override + public void call() { + foreground.call(value); + } + }); + } + }); + } + + public static void andThenOnUi(final Scheduler scheduler, final Action0 background, final Action0 foreground) { + scheduler.createWorker().schedule(new Action0() { + @Override + public void call() { + background.call(); + AndroidSchedulers.mainThread().createWorker().schedule(foreground); + } + }); + } + + /** + * Cache the last value of observables so that every key is associated to only one of them. + * + * @param <K> the type of the key + * @param <V> the type of the value + */ + public static class ObservableCache<K, V> { + + final private Func1<K, Observable<V>> func; + final private Map<K, Observable<V>> cached = new HashMap<>(); + + /** + * Create a new observables cache. + * + * @param func the function transforming a key into an observable + */ + public ObservableCache(final Func1<K, Observable<V>> func) { + this.func = func; + } + + /** + * Get the observable corresponding to a key. If the key has not already been + * seen, the function passed to the constructor will be called to build the observable + * <p/> + * If the observable has already emitted values, only the last one will be remembered. + * + * @param key the key + * @return the observable corresponding to the key + */ + public synchronized Observable<V> get(final K key) { + if (cached.containsKey(key)) { + return cached.get(key); + } + final Observable<V> value = func.call(key).replay(1).refCount(); + cached.put(key, value); + return value; + } + + } + } diff --git a/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java b/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java index eee71ba..0743692 100644 --- a/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java +++ b/main/src/cgeo/geocaching/utils/SimpleCancellableHandler.java @@ -5,6 +5,7 @@ import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.Progress; import android.content.res.Resources; +import android.os.Bundle; import android.os.Message; import java.lang.ref.WeakReference; @@ -21,7 +22,7 @@ public class SimpleCancellableHandler extends CancellableHandler { @Override protected void handleRegularMessage(final Message msg) { - AbstractActivity activity = activityRef.get(); + final AbstractActivity activity = activityRef.get(); if (activity != null && msg.getData() != null && msg.getData().getString(MESSAGE_TEXT) != null) { activity.showToast(msg.getData().getString(MESSAGE_TEXT)); } @@ -30,37 +31,37 @@ public class SimpleCancellableHandler extends CancellableHandler { @Override protected void handleCancel(final Object extra) { - AbstractActivity activity = activityRef.get(); + final AbstractActivity activity = activityRef.get(); if (activity != null) { activity.showToast((String) extra); } dismissProgress(); } - protected final void showToast(int resId) { - AbstractActivity activity = activityRef.get(); + protected final void showToast(final int resId) { + final AbstractActivity activity = activityRef.get(); if (activity != null) { - Resources res = activity.getResources(); + final Resources res = activity.getResources(); activity.showToast(res.getText(resId).toString()); } } protected final void dismissProgress() { - Progress progressDialog = progressDialogRef.get(); + final Progress progressDialog = progressDialogRef.get(); if (progressDialog != null) { progressDialog.dismiss(); } } protected final void setProgressMessage(final String txt) { - Progress progressDialog = progressDialogRef.get(); + final Progress progressDialog = progressDialogRef.get(); if (progressDialog != null) { progressDialog.setMessage(txt); } } protected final void finishActivity() { - AbstractActivity activity = activityRef.get(); + final AbstractActivity activity = activityRef.get(); if (activity != null) { activity.finish(); } @@ -68,7 +69,7 @@ public class SimpleCancellableHandler extends CancellableHandler { } protected void updateStatusMsg(final int resId, final String msg) { - CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get()); + final CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get()); if (activity != null) { setProgressMessage(activity.getResources().getString(resId) + "\n\n" @@ -76,4 +77,15 @@ public class SimpleCancellableHandler extends CancellableHandler { } } + public void sendTextMessage(final int what, final int resId) { + final CacheDetailActivity activity = ((CacheDetailActivity) activityRef.get()); + if (activity != null) { + final Message msg = obtainMessage(what); + final Bundle bundle = new Bundle(); + bundle.putString(SimpleCancellableHandler.MESSAGE_TEXT, activity.getResources().getString(resId)); + msg.setData(bundle); + msg.sendToTarget(); + } + } + } diff --git a/main/src/cgeo/geocaching/utils/StartableHandlerThread.java b/main/src/cgeo/geocaching/utils/StartableHandlerThread.java deleted file mode 100644 index 91ab1d0..0000000 --- a/main/src/cgeo/geocaching/utils/StartableHandlerThread.java +++ /dev/null @@ -1,80 +0,0 @@ -package cgeo.geocaching.utils; - -import org.eclipse.jdt.annotation.NonNull; -import rx.Subscriber; -import rx.functions.Action0; -import rx.subscriptions.Subscriptions; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; - -/** - * Derivated class of {@link android.os.HandlerThread} with an exposed handler and a start/stop mechanism - * based on subscriptions. - */ - -public class StartableHandlerThread extends HandlerThread { - - private final static int START = 1; - private final static int STOP = 2; - - static public interface Callback { - public void start(final Context context, final Handler handler); - public void stop(); - } - - // The handler and the thread are intimely linked, there will be no leak. - @SuppressLint("HandlerLeak") - private class StartableHandler extends Handler { - public StartableHandler() { - super(StartableHandlerThread.this.getLooper()); - } - - @Override - public void handleMessage(final Message message) { - if (callback != null) { - switch (message.what) { - case START: - callback.start((Context) message.obj, this); - break; - case STOP: - callback.stop(); - break; - } - } - } - } - - private Handler handler; - private Callback callback; - - public StartableHandlerThread(@NonNull final String name, final int priority, final Callback callback) { - super(name, priority); - this.callback = callback; - } - - public StartableHandlerThread(@NonNull final String name, final int priority) { - this(name, priority, null); - } - - public synchronized Handler getHandler() { - if (handler == null) { - handler = new StartableHandler(); - } - return handler; - } - - public void start(final Subscriber<?> subscriber, final Context context) { - getHandler().obtainMessage(START, context).sendToTarget(); - subscriber.add(Subscriptions.create(new Action0() { - @Override - public void call() { - getHandler().sendEmptyMessage(STOP); - } - })); - } - -} diff --git a/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java b/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java index 7848d1a..5963e2e 100644 --- a/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java +++ b/main/src/cgeo/geocaching/utils/SynchronizedDateFormat.java @@ -13,7 +13,7 @@ public class SynchronizedDateFormat { format = new SimpleDateFormat(pattern, locale); } - public SynchronizedDateFormat(String pattern, TimeZone timeZone, Locale locale) { + public SynchronizedDateFormat(final String pattern, final TimeZone timeZone, final Locale locale) { format = new SimpleDateFormat(pattern, locale); format.setTimeZone(timeZone); } diff --git a/main/src/cgeo/geocaching/utils/TextUtils.java b/main/src/cgeo/geocaching/utils/TextUtils.java index 77aa167..1f14f8d 100644 --- a/main/src/cgeo/geocaching/utils/TextUtils.java +++ b/main/src/cgeo/geocaching/utils/TextUtils.java @@ -8,6 +8,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.eclipse.jdt.annotation.Nullable; import java.nio.charset.Charset; +import java.text.Collator; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.CRC32; @@ -27,11 +28,11 @@ public final class TextUtils { } /** - * Searches for the pattern p in the data. If the pattern is not found defaultValue is returned + * Searches for the pattern pattern in the data. If the pattern is not found defaultValue is returned * * @param data * Data to search in - * @param p + * @param pattern * Pattern to search for * @param trim * Set to true if the group found should be trim'ed @@ -44,37 +45,38 @@ public final class TextUtils { * @return defaultValue or the n-th group if the pattern matches (trimmed if wanted) */ @SuppressFBWarnings("DM_STRING_CTOR") - public static String getMatch(@Nullable final String data, final Pattern p, final boolean trim, final int group, final String defaultValue, final boolean last) { + public static String getMatch(@Nullable final String data, final Pattern pattern, final boolean trim, final int group, final String defaultValue, final boolean last) { if (data != null) { - - String result = null; - final Matcher matcher = p.matcher(data); - + final Matcher matcher = pattern.matcher(data); if (matcher.find()) { - result = matcher.group(group); - } - if (null != result) { - final Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(result); - result = remover.replaceAll(" "); + String result = matcher.group(group); + while (last && matcher.find()) { + result = matcher.group(group); + } - return trim ? new String(result).trim() : new String(result); - // Java copies the whole page String, when matching with regular expressions - // later this would block the garbage collector, as we only need tiny parts of the page - // see http://developer.android.com/reference/java/lang/String.html#backing_array - // Thus the creating of a new String via String constructor is necessary here!! + if (result != null) { + final Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(result); + result = remover.replaceAll(" "); - // And BTW: You cannot even see that effect in the debugger, but must use a separate memory profiler! + // Some versions of Java copy the whole page String, when matching with regular expressions + // later this would block the garbage collector, as we only need tiny parts of the page + // see http://developer.android.com/reference/java/lang/String.html#backing_array + // Thus the creating of a new String via String constructor is voluntary here!! + // And BTW: You cannot even see that effect in the debugger, but must use a separate memory profiler! + return trim ? new String(result).trim() : new String(result); + } } } + return defaultValue; } /** - * Searches for the pattern p in the data. If the pattern is not found defaultValue is returned + * Searches for the pattern pattern in the data. If the pattern is not found defaultValue is returned * * @param data * Data to search in - * @param p + * @param pattern * Pattern to search for * @param trim * Set to true if the group found should be trim'ed @@ -82,38 +84,33 @@ public final class TextUtils { * Value to return if the pattern is not found * @return defaultValue or the first group if the pattern matches (trimmed if wanted) */ - public static String getMatch(final String data, final Pattern p, final boolean trim, final String defaultValue) { - return TextUtils.getMatch(data, p, trim, 1, defaultValue, false); + public static String getMatch(final String data, final Pattern pattern, final boolean trim, final String defaultValue) { + return TextUtils.getMatch(data, pattern, trim, 1, defaultValue, false); } /** - * Searches for the pattern p in the data. If the pattern is not found defaultValue is returned + * Searches for the pattern pattern in the data. If the pattern is not found defaultValue is returned * * @param data * Data to search in - * @param p + * @param pattern * Pattern to search for * @param defaultValue * Value to return if the pattern is not found * @return defaultValue or the first group if the pattern matches (trimmed) */ - public static String getMatch(@Nullable final String data, final Pattern p, final String defaultValue) { - return TextUtils.getMatch(data, p, true, 1, defaultValue, false); + public static String getMatch(@Nullable final String data, final Pattern pattern, final String defaultValue) { + return TextUtils.getMatch(data, pattern, true, 1, defaultValue, false); } /** - * Searches for the pattern p in the data. + * Searches for the pattern pattern in the data. * - * @param data - * @param p - * @return true if data contains the pattern p + * @return true if data contains the pattern pattern */ - public static boolean matches(final String data, final Pattern p) { - if (data == null) { - return false; - } + public static boolean matches(final String data, final Pattern pattern) { // matcher is faster than String.contains() and more flexible - it takes patterns instead of fixed texts - return p.matcher(data).find(); + return data != null && pattern.matcher(data).find(); } @@ -165,8 +162,6 @@ public final class TextUtils { * Remove all control characters (which are not valid in XML or HTML), as those should not appear in cache texts * anyway * - * @param input - * @return */ public static String removeControlCharacters(final String input) { final Matcher remover = PATTERN_REMOVE_NONPRINTABLE.matcher(input); @@ -182,7 +177,19 @@ public final class TextUtils { */ public static long checksum(final String input) { final CRC32 checksum = new CRC32(); - checksum.update(input.getBytes()); + checksum.update(input.getBytes(CHARSET_UTF8)); return checksum.getValue(); } + + /** + * Build a Collator instance appropriate for comparing strings using the default locale while ignoring the casing. + * + * @return a collator + */ + public static Collator getCollator() { + final Collator collator = Collator.getInstance(); + collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); + collator.setStrength(Collator.TERTIARY); + return collator; + } } diff --git a/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java b/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java index 3cb4f16..d518ac8 100644 --- a/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java +++ b/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java @@ -22,8 +22,8 @@ public class UnknownTagsHandler implements TagHandler { private ListType listType = ListType.Unordered; @Override - public void handleTag(boolean opening, String tag, Editable output, - XMLReader xmlReader) { + public void handleTag(final boolean opening, final String tag, final Editable output, + final XMLReader xmlReader) { if (tag.equalsIgnoreCase("strike") || tag.equals("s")) { handleStrike(opening, output); } else if (tag.equalsIgnoreCase("table")) { @@ -41,7 +41,7 @@ public class UnknownTagsHandler implements TagHandler { } } - private void handleStrike(boolean opening, Editable output) { + private void handleStrike(final boolean opening, final Editable output) { final int length = output.length(); if (opening) { strikePos = length; @@ -61,7 +61,7 @@ public class UnknownTagsHandler implements TagHandler { problematicDetected = true; } - private void handleTd(boolean opening, Editable output) { + private void handleTd(final boolean opening, final Editable output) { // insert bar for each table column, see https://en.wikipedia.org/wiki/Box-drawing_characters if (opening) { if (countCells++ > 0) { @@ -70,7 +70,7 @@ public class UnknownTagsHandler implements TagHandler { } } - private void handleTr(boolean opening, Editable output) { + private void handleTr(final boolean opening, final Editable output) { // insert new line for each table row if (opening) { output.append('\n'); @@ -80,7 +80,7 @@ public class UnknownTagsHandler implements TagHandler { // Ordered lists are handled in a simple manner. They are rendered as Arabic numbers starting at 1 // with no handling for alpha or Roman numbers or arbitrary numbering. - private void handleOl(boolean opening) { + private void handleOl(final boolean opening) { if (opening) { listIndex = 1; listType = ListType.Ordered; @@ -89,7 +89,7 @@ public class UnknownTagsHandler implements TagHandler { } } - private void handleLi(boolean opening, Editable output) { + private void handleLi(final boolean opening, final Editable output) { if (opening) { if (listType == ListType.Ordered) { output.append("\n ").append(String.valueOf(listIndex++)).append(". "); diff --git a/main/src/cgeo/geocaching/utils/XmlUtils.java b/main/src/cgeo/geocaching/utils/XmlUtils.java index c36fb53..004fd1b 100644 --- a/main/src/cgeo/geocaching/utils/XmlUtils.java +++ b/main/src/cgeo/geocaching/utils/XmlUtils.java @@ -17,7 +17,6 @@ public final class XmlUtils { * @param prefix an XML prefix, see {@link XmlSerializer#startTag(String, String)} * @param tag an XML tag * @param text some text to insert, or <tt>null</tt> to omit completely this tag - * @throws IOException */ public static void simpleText(final XmlSerializer serializer, final String prefix, final String tag, final String text) throws IOException { if (text != null) { @@ -34,7 +33,6 @@ public final class XmlUtils { * @param prefix an XML prefix, see {@link XmlSerializer#startTag(String, String)} shared by all tags * @param tagAndText an XML tag, the corresponding text, another XML tag, the corresponding text. <tt>null</tt> texts * will be omitted along with their respective tag. - * @throws IOException */ public static void multipleTexts(final XmlSerializer serializer, final String prefix, final String... tagAndText) throws IOException { for (int i = 0; i < tagAndText.length; i += 2) { diff --git a/main/templates/keys.xml b/main/templates/keys.xml index d40c0e3..b624b86 100644 --- a/main/templates/keys.xml +++ b/main/templates/keys.xml @@ -23,7 +23,7 @@ <string name="oc_ro_okapi_consumer_key" translatable="false">@ocro.okapi.consumer.key@</string> <string name="oc_ro_okapi_consumer_secret" translatable="false">@ocro.okapi.consumer.secret@</string> - <!-- Opencaching.og.uk --> + <!-- Opencaching.org.uk --> <string name="oc_uk_okapi_consumer_key" translatable="false">@ocuk.okapi.consumer.key@</string> <string name="oc_uk_okapi_consumer_secret" translatable="false">@ocuk.okapi.consumer.secret@</string> </resources> diff --git a/main/thirdparty/android/support/v4/app/FragmentListActivity.java b/main/thirdparty/android/support/v4/app/FragmentListActivity.java index a7f8880..9641249 100644 --- a/main/thirdparty/android/support/v4/app/FragmentListActivity.java +++ b/main/thirdparty/android/support/v4/app/FragmentListActivity.java @@ -254,12 +254,10 @@ public class FragmentListActivity extends FragmentActivity { /** * Provide the cursor for the list view. */ - public void setListAdapter(final ListAdapter adapter) { - synchronized (this) { - ensureList(); - mAdapter = adapter; - mList.setAdapter(adapter); - } + public synchronized void setListAdapter(final ListAdapter adapter) { + ensureList(); + mAdapter = adapter; + mList.setAdapter(adapter); } /** diff --git a/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java index 027ff53..01a1872 100644 --- a/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java +++ b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java @@ -32,6 +32,7 @@ import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Locale; +@SuppressWarnings("ALL") public class KXmlSerializer implements XmlSerializer { // static final String UNDEFINED = ":"; diff --git a/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java b/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java index 902de4f..610bee3 100644 --- a/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java +++ b/main/thirdparty/com/google/zxing/integration/android/IntentIntegrator.java @@ -311,7 +311,7 @@ public class IntentIntegrator { Intent intent = new Intent(Intent.ACTION_VIEW, uri); try { activity.startActivity(intent); - } catch (ActivityNotFoundException anfe) { + } catch (ActivityNotFoundException ignored) { // Hmm, market is not installed Log.w(TAG, "Google Play is not installed; cannot install " + packageName); } diff --git a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java b/main/thirdparty/menion/android/locus/LocusDataStorageProvider.java index 03954f5..b575cb5 100644 --- a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java +++ b/main/thirdparty/menion/android/locus/LocusDataStorageProvider.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.apps; +package menion.android.locus; import menion.android.locus.addon.publiclib.geoData.PointsData; import menion.android.locus.addon.publiclib.utils.DataCursor; diff --git a/mapswithme-api/build.gradle b/mapswithme-api/build.gradle index fec7ad7..94cd14f 100644 --- a/mapswithme-api/build.gradle +++ b/mapswithme-api/build.gradle @@ -1,34 +1,19 @@ apply plugin: 'android-library' -dependencies { - compile fileTree(dir: 'libs', include: '*.jar') -} - android { - compileSdkVersion 19 - buildToolsVersion "19.1.0" - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - } + // Define these properties in the gradle.properties file in the root project folder + compileSdkVersion propTargetSdkVersion.toInteger() + buildToolsVersion propBuildToolsVersion - // Move the tests to tests/java, tests/res, etc... - instrumentTest.setRoot('tests') + defaultConfig { + minSdkVersion propMinSdkVersion.toInteger() + targetSdkVersion propTargetSdkVersion.toInteger() + } - // Move the build types to build-types/<type> - // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... - // This moves them out of them default location under src/<type>/... which would - // conflict with src/ being used by the main source set. - // Adding new build types or product flavors should be accompanied - // by a similar customization. - debug.setRoot('build-types/debug') - release.setRoot('build-types/release') - } + sourceSets.main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } } diff --git a/mapswithme-api/lint.xml b/mapswithme-api/lint.xml new file mode 100644 index 0000000..1ff0c2f --- /dev/null +++ b/mapswithme-api/lint.xml @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> + <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> + <issue id="AllowBackup" severity="ignore" /> + <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> + <issue id="ButtonCase" severity="ignore" /> + <issue id="ButtonOrder" severity="ignore" /> + <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> + <issue id="CommitPrefEdits" severity="ignore" /> + <issue id="CommitTransaction" severity="ignore" /> + <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> + <issue id="CutPasteId" severity="ignore" /> + <issue id="DalvikOverride" severity="ignore" /> + <issue id="DefaultLocale" severity="ignore" /> + <issue id="Deprecated" severity="ignore" /> + <issue id="DeviceAdmin" severity="ignore" /> + <issue id="DisableBaselineAlignment" severity="ignore" /> + <issue id="DrawAllocation" severity="ignore" /> + <issue id="DuplicateActivity" severity="ignore" /> + <issue id="DuplicateDefinition" severity="ignore" /> + <issue id="DuplicateIds" severity="ignore" /> + <issue id="DuplicateIncludedIds" severity="ignore" /> + <issue id="DuplicateUsesFeature" severity="ignore" /> + <issue id="EnforceUTF8" severity="ignore" /> + <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> + <issue id="ExportedReceiver" severity="ignore" /> + <issue id="ExportedService" severity="ignore" /> + <issue id="ExtraText" severity="ignore" /> + <issue id="ExtraTranslation" severity="ignore" /> + <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> + <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> + <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> + <issue id="GrantAllUris" severity="ignore" /> + <issue id="GridLayout" severity="ignore" /> + <issue id="HandlerLeak" severity="ignore" /> + <issue id="HardcodedDebugMode" severity="ignore" /> + <issue id="HardcodedText" severity="ignore" /> + <issue id="IconColors" severity="ignore" /> + <issue id="IconDensities" severity="ignore" /> + <issue id="IconDipSize" severity="ignore" /> + <issue id="IconDuplicates" severity="ignore" /> + <issue id="IconDuplicatesConfig" severity="ignore" /> + <issue id="IconExtension" severity="ignore" /> + <issue id="IconLauncherShape" severity="ignore" /> + <issue id="IconLocation" severity="ignore" /> + <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="IconMixedNinePatch" severity="ignore" /> + <issue id="IconNoDpi" severity="ignore" /> + <issue id="IconXmlAndPng" severity="ignore" /> + <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="ImproperProjectLevelStatement" severity="ignore" /> + <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> + <issue id="InconsistentArrays" severity="ignore" /> + <issue id="InconsistentLayout" severity="ignore" /> + <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> + <issue id="InlinedApi" severity="ignore" /> + <issue id="InnerclassSeparator" severity="ignore" /> + <issue id="Instantiatable" severity="ignore" /> + <issue id="InvalidId" severity="ignore" /> + <issue id="InvalidPackage" severity="ignore" /> + <issue id="JavascriptInterface" severity="ignore" /> + <issue id="LabelFor" severity="ignore" /> + <issue id="LibraryCustomView" severity="ignore" /> + <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> + <issue id="MangledCRLF" severity="ignore" /> + <issue id="ManifestOrder" severity="ignore" /> + <issue id="ManifestTypo" severity="ignore" /> + <issue id="MenuTitle" severity="ignore" /> + <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MisplacedStatement" severity="ignore" /> + <issue id="MissingApplicationIcon" severity="ignore" /> + <issue id="MissingId" severity="ignore" /> + <issue id="MissingPrefix" severity="ignore" /> + <issue id="MissingQuantity" severity="ignore" /> + <issue id="MissingRegistered" severity="ignore" /> + <issue id="MissingSuperCall" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> + <issue id="MissingVersion" severity="ignore" /> + <issue id="MockLocation" severity="ignore" /> + <issue id="MultipleUsesSdk" severity="ignore" /> + <issue id="NamespaceTypo" severity="ignore" /> + <issue id="NestedScrolling" severity="ignore" /> + <issue id="NestedWeights" severity="ignore" /> + <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> + <issue id="NotSibling" severity="ignore" /> + <issue id="ObsoleteLayoutParam" severity="ignore" /> + <issue id="OldTargetApi" severity="ignore" /> + <issue id="OnClick" severity="ignore" /> + <issue id="Orientation" severity="ignore" /> + <issue id="Overdraw" severity="ignore" /> + <issue id="Override" severity="ignore" /> + <issue id="PackagedPrivateKey" severity="ignore" /> + <issue id="ParcelCreator" severity="ignore" /> + <issue id="PrivateResource" severity="ignore" /> + <issue id="Proguard" severity="ignore" /> + <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> + <issue id="ProtectedPermissions" severity="ignore" /> + <issue id="PxUsage" severity="ignore" /> + <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> + <issue id="Registered" severity="ignore" /> + <issue id="RequiredSize" severity="ignore" /> + <issue id="ResAuto" severity="ignore" /> + <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> + <issue id="ScrollViewCount" severity="ignore" /> + <issue id="ScrollViewSize" severity="ignore" /> + <issue id="SdCardPath" severity="ignore" /> + <issue id="SecureRandom" severity="ignore" /> + <issue id="ServiceCast" severity="ignore" /> + <issue id="SetJavaScriptEnabled" severity="ignore" /> + <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> + <issue id="SimpleDateFormat" severity="ignore" /> + <issue id="SmallSp" severity="ignore" /> + <issue id="SpUsage" severity="ignore" /> + <issue id="StateListReachable" severity="ignore" /> + <issue id="StringFormatCount" severity="ignore" /> + <issue id="StringFormatInvalid" severity="ignore" /> + <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> + <issue id="Suspicious0dp" severity="ignore" /> + <issue id="SuspiciousImport" severity="ignore" /> + <issue id="TextFields" severity="ignore" /> + <issue id="TextViewEdits" severity="ignore" /> + <issue id="TooDeepLayout" severity="ignore" /> + <issue id="TooManyViews" severity="ignore" /> + <issue id="TrulyRandom" severity="ignore" /> + <issue id="TypographyDashes" severity="ignore" /> + <issue id="TypographyEllipsis" severity="ignore" /> + <issue id="TypographyFractions" severity="ignore" /> + <issue id="TypographyOther" severity="ignore" /> + <issue id="Typos" severity="ignore" /> + <issue id="UniquePermission" severity="ignore" /> + <issue id="UnknownId" severity="ignore" /> + <issue id="UnknownIdInLayout" severity="ignore" /> + <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> + <issue id="UnusedNamespace" severity="ignore" /> + <issue id="UnusedQuantity" severity="ignore" /> + <issue id="UnusedResources" severity="ignore" /> + <issue id="UseCheckPermission" severity="ignore" /> + <issue id="UseCompoundDrawables" severity="ignore" /> + <issue id="UseSparseArrays" severity="ignore" /> + <issue id="UseValueOf" severity="ignore" /> + <issue id="UselessLeaf" severity="ignore" /> + <issue id="UselessParent" severity="ignore" /> + <issue id="UsesMinSdkAttributes" severity="ignore" /> + <issue id="ValidFragment" severity="ignore" /> + <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> + <issue id="ViewTag" severity="ignore" /> + <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> + <issue id="WorldReadableFiles" severity="ignore" /> + <issue id="WorldWriteableFiles" severity="ignore" /> + <issue id="WrongCall" severity="ignore" /> + <issue id="WrongCase" severity="ignore" /> + <issue id="WrongFolder" severity="ignore" /> + <issue id="WrongManifestParent" severity="ignore" /> + <issue id="WrongViewCast" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/mapswithme-api/mapswithme-api.iml b/mapswithme-api/mapswithme-api.iml index 1e6e952..e0f890f 100644 --- a/mapswithme-api/mapswithme-api.iml +++ b/mapswithme-api/mapswithme-api.iml @@ -13,6 +13,7 @@ <facet type="android" name="Android"> <configuration> <option name="LIBRARY_PROJECT" value="true" /> + <option name="UPDATE_PROPERTY_FILES" value="false" /> </configuration> </facet> </component> @@ -25,5 +26,203 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> -</module> - + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/mapswithme-api/project.properties b/mapswithme-api/project.properties index 91d2b02..93c8c3c 100644 --- a/mapswithme-api/project.properties +++ b/mapswithme-api/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-19 +target=android-21 android.library=true diff --git a/mapswithme-api/res/layout/dlg_install_mwm.xml b/mapswithme-api/res/layout/dlg_install_mwm.xml index 0d174a8..1858369 100644 --- a/mapswithme-api/res/layout/dlg_install_mwm.xml +++ b/mapswithme-api/res/layout/dlg_install_mwm.xml @@ -54,16 +54,6 @@ android:background="@drawable/btn_green_selector" android:text="@string/down_pro" /> - <Button - android:id="@+id/btn_lite" - style="@style/promoButton" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_weight="1" - android:background="@drawable/btn_gray_selector" - android:padding="6dp" - android:text="@string/down_lite" /> - </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/mapswithme-api/res/values/strings.xml b/mapswithme-api/res/values/strings.xml index 1955847..d9e3f27 100644 --- a/mapswithme-api/res/values/strings.xml +++ b/mapswithme-api/res/values/strings.xml @@ -1,9 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="mwm_should_be_installed">Offline maps are required to proceed. We have partnered with MapsWithMe to provide you with offline maps of the entire world.\nTo continue please download the app:</string> - <string name="down_lite">Download MapsWithMe Lite (free)</string> - <string name="down_pro">Download MapsWithMe Pro</string> - - <string name="url_pro">http://mapswith.me/get</string> - <string name="url_lite">http://mapswith.me/app</string> + <string name="mwm_should_be_installed">Offline maps are required to proceed. We have partnered with MAPS.ME to provide you with offline maps of the entire world.\nTo continue please download the app:</string> + <string name="down_pro">Download MAPS.ME</string> + <string name="url_pro">http://maps.me/get</string> </resources>
\ No newline at end of file diff --git a/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java b/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java index 5670a5f..480bbe1 100644 --- a/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java +++ b/mapswithme-api/src/com/mapswithme/maps/api/DownloadMapsWithMeDialog.java @@ -41,7 +41,6 @@ public class DownloadMapsWithMeDialog extends Dialog implements android.view.Vie requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.dlg_install_mwm); - findViewById(R.id.btn_lite).setOnClickListener(this); findViewById(R.id.btn_pro).setOnClickListener(this); setOwnerActivity(activity); @@ -59,7 +58,7 @@ public class DownloadMapsWithMeDialog extends Dialog implements android.view.Vie @Override public void onClick(View v) { - String url = getContext().getString(v.getId() == R.id.btn_lite ? R.string.url_lite : R.string.url_pro); + String url = getContext().getString(R.string.url_pro); onDownloadButtonClicked(url); } } diff --git a/play-services-base/.classpath b/play-services-base/.classpath new file mode 100644 index 0000000..f8b9238 --- /dev/null +++ b/play-services-base/.classpath @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"> + <attributes> + <attribute name="ignore_optional_problems" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="src" path="gen"> + <attributes> + <attribute name="ignore_optional_problems" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/play-services-base/.project b/play-services-base/.project new file mode 100644 index 0000000..ac574cb --- /dev/null +++ b/play-services-base/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>play-services-base</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/play-services-base/.settings/org.eclipse.jdt.core.prefs b/play-services-base/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b080d2d --- /dev/null +++ b/play-services-base/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/play-services-base/AndroidManifest.xml b/play-services-base/AndroidManifest.xml new file mode 100644 index 0000000..9e129f9 --- /dev/null +++ b/play-services-base/AndroidManifest.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.android.gms"> + <uses-sdk android:minSdkVersion="9"/> + + <application> + <meta-data + android:name="com.google.android.gms.version" + android:value="@integer/google_play_services_version" /> + </application> + +</manifest> diff --git a/play-services-base/build.xml b/play-services-base/build.xml new file mode 100644 index 0000000..d87d105 --- /dev/null +++ b/play-services-base/build.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="play_services_base" default="help"> + + <!-- The local.properties file is created and updated by the 'android' tool. + It contains the path to the SDK. It should *NOT* be checked into + Version Control Systems. --> + <property file="local.properties" /> + + <!-- The ant.properties file can be created by you. It is only edited by the + 'android' tool to add properties to it. + This is the place to change some Ant specific build properties. + Here are some properties you may want to change/update: + + source.dir + The name of the source directory. Default is 'src'. + out.dir + The name of the output directory. Default is 'bin'. + + For other overridable properties, look at the beginning of the rules + files in the SDK, at tools/ant/build.xml + + Properties related to the SDK location or the project target should + be updated using the 'android' tool with the 'update' action. + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. + + --> + <property file="ant.properties" /> + + <!-- if sdk.dir was not set from one of the property file, then + get it from the ANDROID_HOME env var. + This must be done before we load project.properties since + the proguard config can use sdk.dir --> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + + <!-- The project.properties file is created and updated by the 'android' + tool, as well as ADT. + + This contains project specific properties such as project target, and library + dependencies. Lower level build properties are stored in ant.properties + (or in .classpath for Eclipse projects). + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> + <loadproperties srcFile="project.properties" /> + + <!-- quick check on sdk.dir --> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." + unless="sdk.dir" /> + + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> + + <!-- Import the actual build file. + + To customize existing targets, there are two options: + - Customize only one target: + - copy/paste the target into this file, *before* the + <import> task. + - customize it to your needs. + - Customize the whole content of build.xml + - copy/paste the content of the rules files (minus the top node) + into this file, replacing the <import> task. + - customize to your needs. + + *********************** + ****** IMPORTANT ****** + *********************** + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, + in order to avoid having your file be overridden by tools such as "android update project" + --> + <!-- version-tag: 1 --> + <import file="${sdk.dir}/tools/ant/build.xml" /> + +</project> diff --git a/play-services-base/libs/play-services-base.jar b/play-services-base/libs/play-services-base.jar Binary files differnew file mode 100644 index 0000000..a7666a9 --- /dev/null +++ b/play-services-base/libs/play-services-base.jar diff --git a/play-services-base/lint.xml b/play-services-base/lint.xml new file mode 100644 index 0000000..715caf3 --- /dev/null +++ b/play-services-base/lint.xml @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> + <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> + <issue id="AllowBackup" severity="ignore" /> + <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> + <issue id="ButtonCase" severity="ignore" /> + <issue id="ButtonOrder" severity="ignore" /> + <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> + <issue id="CommitPrefEdits" severity="ignore" /> + <issue id="CommitTransaction" severity="ignore" /> + <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> + <issue id="CutPasteId" severity="ignore" /> + <issue id="DalvikOverride" severity="ignore" /> + <issue id="DefaultLocale" severity="ignore" /> + <issue id="Deprecated" severity="ignore" /> + <issue id="DeviceAdmin" severity="ignore" /> + <issue id="DisableBaselineAlignment" severity="ignore" /> + <issue id="DrawAllocation" severity="ignore" /> + <issue id="DuplicateActivity" severity="ignore" /> + <issue id="DuplicateDefinition" severity="ignore" /> + <issue id="DuplicateIds" severity="ignore" /> + <issue id="DuplicateIncludedIds" severity="ignore" /> + <issue id="DuplicateUsesFeature" severity="ignore" /> + <issue id="EnforceUTF8" severity="ignore" /> + <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> + <issue id="ExportedReceiver" severity="ignore" /> + <issue id="ExportedService" severity="ignore" /> + <issue id="ExtraText" severity="ignore" /> + <issue id="ExtraTranslation" severity="ignore" /> + <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> + <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> + <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> + <issue id="GrantAllUris" severity="ignore" /> + <issue id="GridLayout" severity="ignore" /> + <issue id="HandlerLeak" severity="ignore" /> + <issue id="HardcodedDebugMode" severity="ignore" /> + <issue id="HardcodedText" severity="ignore" /> + <issue id="IconColors" severity="ignore" /> + <issue id="IconDensities" severity="ignore" /> + <issue id="IconDipSize" severity="ignore" /> + <issue id="IconDuplicates" severity="ignore" /> + <issue id="IconDuplicatesConfig" severity="ignore" /> + <issue id="IconExtension" severity="ignore" /> + <issue id="IconLauncherShape" severity="ignore" /> + <issue id="IconLocation" severity="ignore" /> + <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="IconMixedNinePatch" severity="ignore" /> + <issue id="IconNoDpi" severity="ignore" /> + <issue id="IconXmlAndPng" severity="ignore" /> + <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> + <issue id="InconsistentArrays" severity="ignore" /> + <issue id="InconsistentLayout" severity="ignore" /> + <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> + <issue id="InlinedApi" severity="ignore" /> + <issue id="InnerclassSeparator" severity="ignore" /> + <issue id="Instantiatable" severity="ignore" /> + <issue id="InvalidId" severity="ignore" /> + <issue id="InvalidPackage" severity="ignore" /> + <issue id="JavascriptInterface" severity="ignore" /> + <issue id="LabelFor" severity="ignore" /> + <issue id="LibraryCustomView" severity="ignore" /> + <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> + <issue id="MangledCRLF" severity="ignore" /> + <issue id="ManifestOrder" severity="ignore" /> + <issue id="ManifestTypo" severity="ignore" /> + <issue id="MenuTitle" severity="ignore" /> + <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MissingApplicationIcon" severity="ignore" /> + <issue id="MissingId" severity="ignore" /> + <issue id="MissingPrefix" severity="ignore" /> + <issue id="MissingQuantity" severity="ignore" /> + <issue id="MissingRegistered" severity="ignore" /> + <issue id="MissingSuperCall" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> + <issue id="MissingVersion" severity="ignore" /> + <issue id="MockLocation" severity="ignore" /> + <issue id="MultipleUsesSdk" severity="ignore" /> + <issue id="NamespaceTypo" severity="ignore" /> + <issue id="NestedScrolling" severity="ignore" /> + <issue id="NestedWeights" severity="ignore" /> + <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> + <issue id="NotSibling" severity="ignore" /> + <issue id="ObsoleteLayoutParam" severity="ignore" /> + <issue id="OldTargetApi" severity="ignore" /> + <issue id="OnClick" severity="ignore" /> + <issue id="Orientation" severity="ignore" /> + <issue id="Overdraw" severity="ignore" /> + <issue id="Override" severity="ignore" /> + <issue id="PackagedPrivateKey" severity="ignore" /> + <issue id="ParcelCreator" severity="ignore" /> + <issue id="PrivateResource" severity="ignore" /> + <issue id="Proguard" severity="ignore" /> + <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> + <issue id="ProtectedPermissions" severity="ignore" /> + <issue id="PxUsage" severity="ignore" /> + <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> + <issue id="Registered" severity="ignore" /> + <issue id="RequiredSize" severity="ignore" /> + <issue id="ResAuto" severity="ignore" /> + <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> + <issue id="ScrollViewCount" severity="ignore" /> + <issue id="ScrollViewSize" severity="ignore" /> + <issue id="SdCardPath" severity="ignore" /> + <issue id="SecureRandom" severity="ignore" /> + <issue id="ServiceCast" severity="ignore" /> + <issue id="SetJavaScriptEnabled" severity="ignore" /> + <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> + <issue id="SimpleDateFormat" severity="ignore" /> + <issue id="SmallSp" severity="ignore" /> + <issue id="SpUsage" severity="ignore" /> + <issue id="StateListReachable" severity="ignore" /> + <issue id="StringFormatCount" severity="ignore" /> + <issue id="StringFormatInvalid" severity="ignore" /> + <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> + <issue id="Suspicious0dp" severity="ignore" /> + <issue id="SuspiciousImport" severity="ignore" /> + <issue id="TextFields" severity="ignore" /> + <issue id="TextViewEdits" severity="ignore" /> + <issue id="TooDeepLayout" severity="ignore" /> + <issue id="TooManyViews" severity="ignore" /> + <issue id="TrulyRandom" severity="ignore" /> + <issue id="TypographyDashes" severity="ignore" /> + <issue id="TypographyEllipsis" severity="ignore" /> + <issue id="TypographyFractions" severity="ignore" /> + <issue id="TypographyOther" severity="ignore" /> + <issue id="Typos" severity="ignore" /> + <issue id="UniquePermission" severity="ignore" /> + <issue id="UnknownId" severity="ignore" /> + <issue id="UnknownIdInLayout" severity="ignore" /> + <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> + <issue id="UnusedNamespace" severity="ignore" /> + <issue id="UnusedQuantity" severity="ignore" /> + <issue id="UnusedResources" severity="ignore" /> + <issue id="UseCheckPermission" severity="ignore" /> + <issue id="UseCompoundDrawables" severity="ignore" /> + <issue id="UseSparseArrays" severity="ignore" /> + <issue id="UseValueOf" severity="ignore" /> + <issue id="UselessLeaf" severity="ignore" /> + <issue id="UselessParent" severity="ignore" /> + <issue id="UsesMinSdkAttributes" severity="ignore" /> + <issue id="ValidFragment" severity="ignore" /> + <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> + <issue id="ViewTag" severity="ignore" /> + <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> + <issue id="WorldReadableFiles" severity="ignore" /> + <issue id="WorldWriteableFiles" severity="ignore" /> + <issue id="WrongCall" severity="ignore" /> + <issue id="WrongCase" severity="ignore" /> + <issue id="WrongFolder" severity="ignore" /> + <issue id="WrongManifestParent" severity="ignore" /> + <issue id="WrongViewCast" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/play-services-base/play-services-base.iml b/play-services-base/play-services-base.iml new file mode 100644 index 0000000..3525dde --- /dev/null +++ b/play-services-base/play-services-base.iml @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="android" name="Android"> + <configuration> + <option name="LIBRARY_PROJECT" value="true" /> + <option name="UPDATE_PROPERTY_FILES" value="false" /> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module-library" exported=""> + <library> + <CLASSES> + <root url="file://$MODULE_DIR$/libs" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" /> + </library> + </orderEntry> + </component> + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/play-services-base/proguard.txt b/play-services-base/proguard.txt new file mode 100644 index 0000000..5e03f78 --- /dev/null +++ b/play-services-base/proguard.txt @@ -0,0 +1,24 @@ +-keep class * extends java.util.ListResourceBundle { + protected Object[][] getContents(); +} + +# Keep SafeParcelable value, needed for reflection. This is required to support backwards +# compatibility of some classes. +-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { + public static final *** NULL; +} + +# Keep the names of classes/members we need for client functionality. +-keepnames @com.google.android.gms.common.annotation.KeepName class * +-keepclassmembernames class * { + @com.google.android.gms.common.annotation.KeepName *; +} + +# Needed for Parcelable/SafeParcelable Creators to not get stripped +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; +} + +# classes introduced in higher API levels than we use as target +-dontwarn com.google.android.gms.common.SupportErrorDialogFragment +-dontwarn com.google.android.gms.common.api.**
\ No newline at end of file diff --git a/play-services-base/project.properties b/play-services-base/project.properties new file mode 100644 index 0000000..664c438 --- /dev/null +++ b/play-services-base/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.txt + +# Project target. +target=Google Inc.:Google APIs:21 +android.library=true diff --git a/play-services-base/res/color/common_signin_btn_text_dark.xml b/play-services-base/res/color/common_signin_btn_text_dark.xml new file mode 100644 index 0000000..a615ba2 --- /dev/null +++ b/play-services-base/res/color/common_signin_btn_text_dark.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:color="@color/common_signin_btn_dark_text_pressed" /> + <item + android:state_enabled="false" + android:state_focused="true" + android:color="@color/common_signin_btn_dark_text_disabled" /> + <item + android:state_focused="true" + android:color="@color/common_signin_btn_dark_text_focused" /> + <item + android:state_enabled="false" + android:color="@color/common_signin_btn_dark_text_disabled" /> + <item + android:color="@color/common_signin_btn_dark_text_default" /> +</selector> diff --git a/play-services-base/res/color/common_signin_btn_text_light.xml b/play-services-base/res/color/common_signin_btn_text_light.xml new file mode 100644 index 0000000..6620668 --- /dev/null +++ b/play-services-base/res/color/common_signin_btn_text_light.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:color="@color/common_signin_btn_light_text_pressed" /> + <item + android:state_enabled="false" + android:state_focused="true" + android:color="@color/common_signin_btn_light_text_disabled" /> + <item + android:state_focused="true" + android:color="@color/common_signin_btn_light_text_focused" /> + <item + android:state_enabled="false" + android:color="@color/common_signin_btn_light_text_disabled" /> + <item + android:color="@color/common_signin_btn_light_text_default" /> +</selector> diff --git a/play-services-base/res/drawable-hdpi/common_full_open_on_phone.png b/play-services-base/res/drawable-hdpi/common_full_open_on_phone.png Binary files differnew file mode 100644 index 0000000..89423e0 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_full_open_on_phone.png diff --git a/play-services-base/res/drawable-hdpi/common_ic_googleplayservices.png b/play-services-base/res/drawable-hdpi/common_ic_googleplayservices.png Binary files differnew file mode 100644 index 0000000..cd0f751 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_ic_googleplayservices.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..0f9e791 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..570e432 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..570e432 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..0f9e791 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..f507b9f --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png Binary files differnew file mode 100644 index 0000000..d5625e5 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..aea3c0d --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png Binary files differnew file mode 100644 index 0000000..849e89f --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..f4ab2f2 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..9fe611d --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..bbcde39 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..53957b6 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..53957b6 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..bbcde39 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..000d12e --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png Binary files differnew file mode 100644 index 0000000..d927940 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..67f263c --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png Binary files differnew file mode 100644 index 0000000..96324c5 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..e450312 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png diff --git a/play-services-base/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png b/play-services-base/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..fb94b77 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png diff --git a/play-services-base/res/drawable-hdpi/ic_plusone_medium_off_client.png b/play-services-base/res/drawable-hdpi/ic_plusone_medium_off_client.png Binary files differnew file mode 100644 index 0000000..b89b884 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/ic_plusone_medium_off_client.png diff --git a/play-services-base/res/drawable-hdpi/ic_plusone_small_off_client.png b/play-services-base/res/drawable-hdpi/ic_plusone_small_off_client.png Binary files differnew file mode 100644 index 0000000..816ec91 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/ic_plusone_small_off_client.png diff --git a/play-services-base/res/drawable-hdpi/ic_plusone_standard_off_client.png b/play-services-base/res/drawable-hdpi/ic_plusone_standard_off_client.png Binary files differnew file mode 100644 index 0000000..949ed72 --- /dev/null +++ b/play-services-base/res/drawable-hdpi/ic_plusone_standard_off_client.png diff --git a/play-services-base/res/drawable-hdpi/ic_plusone_tall_off_client.png b/play-services-base/res/drawable-hdpi/ic_plusone_tall_off_client.png Binary files differnew file mode 100644 index 0000000..306a47c --- /dev/null +++ b/play-services-base/res/drawable-hdpi/ic_plusone_tall_off_client.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..dddcbeb --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..58b75bd --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..58b75bd --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..dddcbeb --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..7d9ed78 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png Binary files differnew file mode 100644 index 0000000..0ca401d --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..f2c3f55 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png Binary files differnew file mode 100644 index 0000000..83b4fc9 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..dd74fe8 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..b7dc7aa --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..efdfe2e --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..c7650b0 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..c7650b0 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..efdfe2e --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..8c76283 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png Binary files differnew file mode 100644 index 0000000..abd26bc --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..28181c3 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png Binary files differnew file mode 100644 index 0000000..34957fa --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..e923ee9 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png diff --git a/play-services-base/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png b/play-services-base/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..34cf6bb --- /dev/null +++ b/play-services-base/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png diff --git a/play-services-base/res/drawable-mdpi/ic_plusone_medium_off_client.png b/play-services-base/res/drawable-mdpi/ic_plusone_medium_off_client.png Binary files differnew file mode 100644 index 0000000..05a8cb9 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/ic_plusone_medium_off_client.png diff --git a/play-services-base/res/drawable-mdpi/ic_plusone_small_off_client.png b/play-services-base/res/drawable-mdpi/ic_plusone_small_off_client.png Binary files differnew file mode 100644 index 0000000..103f364 --- /dev/null +++ b/play-services-base/res/drawable-mdpi/ic_plusone_small_off_client.png diff --git a/play-services-base/res/drawable-mdpi/ic_plusone_standard_off_client.png b/play-services-base/res/drawable-mdpi/ic_plusone_standard_off_client.png Binary files differnew file mode 100644 index 0000000..2ea233e --- /dev/null +++ b/play-services-base/res/drawable-mdpi/ic_plusone_standard_off_client.png diff --git a/play-services-base/res/drawable-mdpi/ic_plusone_tall_off_client.png b/play-services-base/res/drawable-mdpi/ic_plusone_tall_off_client.png Binary files differnew file mode 100644 index 0000000..417d8ee --- /dev/null +++ b/play-services-base/res/drawable-mdpi/ic_plusone_tall_off_client.png diff --git a/play-services-base/res/drawable-tvdpi/ic_plusone_medium_off_client.png b/play-services-base/res/drawable-tvdpi/ic_plusone_medium_off_client.png Binary files differnew file mode 100644 index 0000000..be47840 --- /dev/null +++ b/play-services-base/res/drawable-tvdpi/ic_plusone_medium_off_client.png diff --git a/play-services-base/res/drawable-tvdpi/ic_plusone_small_off_client.png b/play-services-base/res/drawable-tvdpi/ic_plusone_small_off_client.png Binary files differnew file mode 100644 index 0000000..f629f40 --- /dev/null +++ b/play-services-base/res/drawable-tvdpi/ic_plusone_small_off_client.png diff --git a/play-services-base/res/drawable-tvdpi/ic_plusone_standard_off_client.png b/play-services-base/res/drawable-tvdpi/ic_plusone_standard_off_client.png Binary files differnew file mode 100644 index 0000000..a4f50f1 --- /dev/null +++ b/play-services-base/res/drawable-tvdpi/ic_plusone_standard_off_client.png diff --git a/play-services-base/res/drawable-tvdpi/ic_plusone_tall_off_client.png b/play-services-base/res/drawable-tvdpi/ic_plusone_tall_off_client.png Binary files differnew file mode 100644 index 0000000..e81f7c5 --- /dev/null +++ b/play-services-base/res/drawable-tvdpi/ic_plusone_tall_off_client.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..9044a11 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..e94a49b --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..e94a49b --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..9044a11 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..bfe4f04 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png Binary files differnew file mode 100644 index 0000000..876884f --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..b3e6dd5 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png Binary files differnew file mode 100644 index 0000000..5a888f2 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..d0f7b4c --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..0db6b06 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..d182b5e --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..47e2aea --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..47e2aea --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..d182b5e --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..64e9706 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png Binary files differnew file mode 100644 index 0000000..0fd8cdd --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..3427b47 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png Binary files differnew file mode 100644 index 0000000..31e38c4 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..e6a7880 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png diff --git a/play-services-base/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..972962d --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png diff --git a/play-services-base/res/drawable-xhdpi/ic_plusone_medium_off_client.png b/play-services-base/res/drawable-xhdpi/ic_plusone_medium_off_client.png Binary files differnew file mode 100644 index 0000000..7ce2f8a --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/ic_plusone_medium_off_client.png diff --git a/play-services-base/res/drawable-xhdpi/ic_plusone_small_off_client.png b/play-services-base/res/drawable-xhdpi/ic_plusone_small_off_client.png Binary files differnew file mode 100644 index 0000000..568305f --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/ic_plusone_small_off_client.png diff --git a/play-services-base/res/drawable-xhdpi/ic_plusone_standard_off_client.png b/play-services-base/res/drawable-xhdpi/ic_plusone_standard_off_client.png Binary files differnew file mode 100644 index 0000000..13b2ed5 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/ic_plusone_standard_off_client.png diff --git a/play-services-base/res/drawable-xhdpi/ic_plusone_tall_off_client.png b/play-services-base/res/drawable-xhdpi/ic_plusone_tall_off_client.png Binary files differnew file mode 100644 index 0000000..c8eb4b8 --- /dev/null +++ b/play-services-base/res/drawable-xhdpi/ic_plusone_tall_off_client.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..c97f349 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..34cbff1 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..34cbff1 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..c97f349 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..702c49b --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png Binary files differnew file mode 100644 index 0000000..06ad5a5 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..af160fc --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png Binary files differnew file mode 100644 index 0000000..c647fb4 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..fd0a431 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..f8ce5a6 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png Binary files differnew file mode 100644 index 0000000..b491f62 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..777c8d6 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png Binary files differnew file mode 100644 index 0000000..777c8d6 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png Binary files differnew file mode 100644 index 0000000..b491f62 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png Binary files differnew file mode 100644 index 0000000..c8a8f1c --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png Binary files differnew file mode 100644 index 0000000..bcd0d0c --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png Binary files differnew file mode 100644 index 0000000..ac75dad --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png Binary files differnew file mode 100644 index 0000000..c19afad --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png Binary files differnew file mode 100644 index 0000000..c490441 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png diff --git a/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png Binary files differnew file mode 100644 index 0000000..c52be74 --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png diff --git a/play-services-base/res/drawable-xxhdpi/ic_plusone_medium_off_client.png b/play-services-base/res/drawable-xxhdpi/ic_plusone_medium_off_client.png Binary files differnew file mode 100644 index 0000000..210fb4a --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/ic_plusone_medium_off_client.png diff --git a/play-services-base/res/drawable-xxhdpi/ic_plusone_small_off_client.png b/play-services-base/res/drawable-xxhdpi/ic_plusone_small_off_client.png Binary files differnew file mode 100644 index 0000000..71855ad --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/ic_plusone_small_off_client.png diff --git a/play-services-base/res/drawable-xxhdpi/ic_plusone_standard_off_client.png b/play-services-base/res/drawable-xxhdpi/ic_plusone_standard_off_client.png Binary files differnew file mode 100644 index 0000000..ff43fbe --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/ic_plusone_standard_off_client.png diff --git a/play-services-base/res/drawable-xxhdpi/ic_plusone_tall_off_client.png b/play-services-base/res/drawable-xxhdpi/ic_plusone_tall_off_client.png Binary files differnew file mode 100644 index 0000000..1bb932a --- /dev/null +++ b/play-services-base/res/drawable-xxhdpi/ic_plusone_tall_off_client.png diff --git a/play-services-base/res/drawable/common_signin_btn_icon_dark.xml b/play-services-base/res/drawable/common_signin_btn_icon_dark.xml new file mode 100644 index 0000000..dd1cf67 --- /dev/null +++ b/play-services-base/res/drawable/common_signin_btn_icon_dark.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:drawable="@drawable/common_signin_btn_icon_pressed_dark" /> + <item + android:state_enabled="false" + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_icon_disabled_focus_dark" /> + <item + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_icon_focus_dark" /> + <item + android:state_enabled="false" + android:drawable="@drawable/common_signin_btn_icon_disabled_dark" /> + <item + android:drawable="@drawable/common_signin_btn_icon_normal_dark" /> +</selector> diff --git a/play-services-base/res/drawable/common_signin_btn_icon_light.xml b/play-services-base/res/drawable/common_signin_btn_icon_light.xml new file mode 100644 index 0000000..abf412b --- /dev/null +++ b/play-services-base/res/drawable/common_signin_btn_icon_light.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:drawable="@drawable/common_signin_btn_icon_pressed_light" /> + <item + android:state_enabled="false" + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_icon_disabled_focus_light" /> + <item + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_icon_focus_light" /> + <item + android:state_enabled="false" + android:drawable="@drawable/common_signin_btn_icon_disabled_light" /> + <item + android:drawable="@drawable/common_signin_btn_icon_normal_light" /> +</selector> diff --git a/play-services-base/res/drawable/common_signin_btn_text_dark.xml b/play-services-base/res/drawable/common_signin_btn_text_dark.xml new file mode 100644 index 0000000..2d92217 --- /dev/null +++ b/play-services-base/res/drawable/common_signin_btn_text_dark.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:drawable="@drawable/common_signin_btn_text_pressed_dark" /> + <item + android:state_enabled="false" + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_text_disabled_focus_dark" /> + <item + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_text_focus_dark" /> + <item + android:state_enabled="false" + android:drawable="@drawable/common_signin_btn_text_disabled_dark" /> + <item + android:drawable="@drawable/common_signin_btn_text_normal_dark" /> +</selector> diff --git a/play-services-base/res/drawable/common_signin_btn_text_light.xml b/play-services-base/res/drawable/common_signin_btn_text_light.xml new file mode 100644 index 0000000..810c021 --- /dev/null +++ b/play-services-base/res/drawable/common_signin_btn_text_light.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:drawable="@drawable/common_signin_btn_text_pressed_light" /> + <item + android:state_enabled="false" + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_text_disabled_focus_light" /> + <item + android:state_focused="true" + android:drawable="@drawable/common_signin_btn_text_focus_light" /> + <item + android:state_enabled="false" + android:drawable="@drawable/common_signin_btn_text_disabled_light" /> + <item + android:drawable="@drawable/common_signin_btn_text_normal_light" /> +</selector> diff --git a/play-services-base/res/raw/gtm_analytics b/play-services-base/res/raw/gtm_analytics Binary files differnew file mode 100644 index 0000000..c9f49be --- /dev/null +++ b/play-services-base/res/raw/gtm_analytics diff --git a/play-services-base/res/values-af/common_strings.xml b/play-services-base/res/values-af/common_strings.xml new file mode 100644 index 0000000..66766e0 --- /dev/null +++ b/play-services-base/res/values-af/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play Services-fout"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"\'n Program vereis dat Google Play Services geïnstalleer word."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"\'n Program vereis dat Google Play Services opgedateer word."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"\'n Program vereis \'n opdatering na die Android Wear-program."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"\'n Program vereis dat Google Play Services geaktiveer word."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Versoek deur <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Kry Google Play-dienste"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou foon is nie."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou tablet is nie."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Kry Google Play-dienste"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktiveer Google Play-dienste"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Hierdie program sal nie werk tensy jy Google Play-dienste aktiveer nie."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktiveer Google Play-dienste"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Dateer Google Play-dienste op"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Dateer Android Wear op"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Hierdie program sal nie loop nie, tensy jy Google Play-dienste opdateer."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Hierdie program sal nie werk tensy jy die Android Wear-program opdateer nie."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netwerkfout"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"\'n Dataverbinding is nodig om aan Google Play-dienste te koppel."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ongeldige rekening"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Die gespesifiseerde rekening bestaan nie op hierdie toestel nie. Kies asseblief \'n ander rekening."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Onbekende probleem met Google Play-dienste."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-dienste"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-dienste, waarop sommige van jou programme staatmaak, werk nie met jou toestel nie. Kontak asseblief die vervaardiger vir bystand."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Dateer op"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Meld aan"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Meld aan met Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Maak op foon oop"</string> +</resources> diff --git a/play-services-base/res/values-am/common_strings.xml b/play-services-base/res/values-am/common_strings.xml new file mode 100644 index 0000000..abaae9f --- /dev/null +++ b/play-services-base/res/values-am/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"የGoogle Play አገáˆáŒáˆŽá‰¶á‰½ ስህተት"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"አንድ መተáŒá‰ ሪያ የGoogle Play አገáˆáŒáˆŽá‰¶á‰½ እንዲጫኑ á‹áˆáˆáŒ‹áˆá¢"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"አንድ መተáŒá‰ ሪያ የGoogle Play አገáˆáŒáˆŽá‰¶á‰½ እንዲዘáˆáŠ‘ á‹áˆáˆáŒ‹áˆá¢"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"አንድ መተáŒá‰ ሪያ የAndroid Wear መተáŒá‰ ሪያ á‹áˆ›áŠ” ያስáˆáˆáŒˆá‹‹áˆá¢"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"አንድ መተáŒá‰ ሪያ የGoogle Play አገáˆáŒáˆŽá‰¶á‰½ እንዲáŠá‰ á‹áˆáˆáŒ‹áˆá¢"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> የተጠየቀ"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• አáŒáŠ"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"á‹áˆ… መተáŒá‰ ሪያ ያለ Google Play አገáˆáŒáˆŽá‰¶á‰½ አá‹áˆ°áˆ«áˆá£ እáŠáˆ± á‹°áŒáˆž ስáˆáŠá‹Ž ላዠየሉáˆá¢"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"á‹áˆ… መተáŒá‰ ሪያ ያለ Google Play አገáˆáŒáˆŽá‰¶á‰½ አá‹áˆ°áˆ«áˆá£ እáŠáˆ± á‹°áŒáˆž ጡባዊዎ ላዠየሉáˆá¢"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• አáŒáŠ"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• አንቃ"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• እስካላáŠá‰ ድረስ á‹áˆ… መተáŒá‰ ሪያ አá‹áˆ°áˆ«áˆá¢"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• አንቃ"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• ያዘáˆáŠ‘"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wearን ያዘáˆáŠ‘"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Google Play አገáˆáŒáˆŽá‰¶á‰½áŠ• እስኪያዘáˆáŠ‘ ድረስ á‹áˆ… መተáŒá‰ ሪያ አá‹áˆ°áˆ«áˆá¢"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"የAndroid Wear መተáŒá‰ ሪያá‹áŠ• እስኪያዘáˆáŠ‘ት ድረስ á‹áˆ… መተáŒá‰ ሪያ አያሄድáˆá¢"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"የአá‹á‰³áˆ¨ መረብ ስህተት"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ከGoogle Play አገáˆáŒáˆŽá‰¶á‰½ ጋሠለመገናኘት የá‹áˆ‚ብ áŒáŠ•áŠ™áŠá‰µ ያስáˆáˆáŒ‹áˆá¢"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"áˆáŠ á‹«áˆáˆ†áŠ መለያ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"የተገለጸዠመለያ በዚህ መሣሪያ ላዠየለáˆá¢ እባáŠá‹ የተለየ መለያ á‹áˆáˆ¨áŒ¡á¢"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"በGoogle Play አገáˆáŒáˆŽá‰¶á‰½ ላዠያáˆá‰³á‹ˆá‰€ ችáŒáˆá¢"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play አገáˆáŒáˆŽá‰¶á‰½"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"የGoogle Play አገáˆáŒáˆŽá‰¶á‰½á£ አንዳንድ መተáŒá‰ ሪያዎችዎ በእሱ ላዠጥገኛ የሆኑትᣠበመሣሪያዎ አá‹á‹°áŒˆááˆá¢ እባáŠá‹Ž ለእáˆá‹³á‰³ አáˆáˆ«á‰¹áŠ• á‹«áŒáŠ™á¢"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ያዘáˆáŠ‘"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"áŒá‰£"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"በGoogle á‹áŒá‰¡"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ስáˆáŠ ላዠáŠáˆá‰µ"</string> +</resources> diff --git a/play-services-base/res/values-ar/common_strings.xml b/play-services-base/res/values-ar/common_strings.xml new file mode 100644 index 0000000..b11c84c --- /dev/null +++ b/play-services-base/res/values-ar/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"â€Ø®Ø·Ø£ ÙÙŠ خدمات Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"â€ÙŠØªØ·Ù„ب Ø£Øد التطبيقات تثبيت خدمات Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"â€ÙŠØªØ·Ù„ب Ø£Øد التطبيقات تØديث خدمات Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"â€ÙŠØªØ·Ù„ب Ø£Øد التطبيقات تØديثًا لتطبيق Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"â€ÙŠØªØ·Ù„ب Ø£Øد التطبيقات تمكين خدمات Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"تم الطلب عن طريق <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"â€Ø§Ù„Øصول على خدمات Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"â€Ù„Ù† يتم تشغيل هذا التطبيق بدون خدمات Google PlayØŒ والتي لا تتوÙر ÙÙŠ هاتÙÙƒ."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"â€Ù„Ù† يتم تشغيل هذا التطبيق بدون خدمات Google PlayØŒ والتي لا تتوÙر ÙÙŠ جهازك اللوØÙŠ."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"â€Ø§Ù„Øصول على خدمات Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"â€ØªÙ…كين خدمات Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"â€Ù„Ù† يعمل هذا التطبيق ما لم يتم تمكين خدمات Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"â€ØªÙ…كين خدمات Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"â€ØªØديث خدمات Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"â€ØªØديث Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"â€Ù„Ù† يتم تشغيل هذا التطبيق ما لم تØدÙّث خدمات Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"â€Ù„Ù† يتم تشغيل هذا التطبيق ما لم تØدÙّث تطبيق Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"خطأ ÙÙŠ الشبكة"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"â€ÙŠØªØ·Ù„ب الاتصال بخدمات Google Play وجود اتصال بيانات."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Øساب غير صالØ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"الØساب الذي تمّ تØديده غير موجود على الجهاز. ÙŠÙرجى اختيار Øساب آخر."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"â€Øدثت مشكلة غير معروÙØ© ÙÙŠ خدمات Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"â€Ø®Ø¯Ù…ات Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"â€Ø®Ø¯Ù…ات Google Play التي تستجيب لها بعض تطبيقاتك لا تعمل على جهازك. ÙŠÙرجى الاتصال بجهة التصنيع للØصول على المساعدة."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"تØديث"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"تسجيل الدخول"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"â€ØªØ³Ø¬ÙŠÙ„ الدخول باستخدام Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ÙØªØ Ø¹Ù„Ù‰ الهاتÙ"</string> +</resources> diff --git a/play-services-base/res/values-bg/common_strings.xml b/play-services-base/res/values-bg/common_strings.xml new file mode 100644 index 0000000..93d4469 --- /dev/null +++ b/play-services-base/res/values-bg/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Грешка в уÑлугите за Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Приложение изиÑква инÑталирането на уÑлугите за Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Приложение изиÑква актуализирането на уÑлугите за Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Приложение изиÑква актуализиране на Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Приложение изиÑква активирането на уÑлугите за Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"ЗаÑвено от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"ИзтеглÑне на уÑлугите за Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Това приложение нÑма да Ñе изпълнÑва без уÑлугите за Google Play, които липÑват в телефона ви."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Това приложение нÑма да Ñе изпълнÑва без уÑлугите за Google Play, които липÑват в таблета ви."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"УÑлуги за Google Play: Изтегл."</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ðктивиране на уÑлугите за Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Това приложение нÑма да работи, оÑвен ако не активирате уÑлугите за Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"УÑлуги за Google Play: Ðктив."</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ðктуализиране на уÑлугите за Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Ðктуализиране на Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Това приложение нÑма да Ñе изпълнÑва, оÑвен ако не актуализирате уÑлугите за Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Това приложение нÑма да Ñтартира, оÑвен ако не актуализирате Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Грешка в мрежата"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"За Ñвързване Ñ ÑƒÑлугите за Google Play Ñе изиÑква връзка за данни."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ðевалиден профил"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ПоÑочениÑÑ‚ профил не ÑъщеÑтвува на това уÑтройÑтво. МолÑ, изберете друг."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"ÐеизвеÑтен проблем Ñ ÑƒÑлугите за Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"УÑлуги за Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"УÑлугите за Google Play, на които разчитат нÑкои от приложениÑта ви, не Ñе поддържат от уÑтройÑтвото ви. МолÑ, Ñвържете Ñе Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»Ñ Ð·Ð° помощ."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ðктуализиране"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Вход"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Вход Ñ Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ОтварÑне в телефона"</string> +</resources> diff --git a/play-services-base/res/values-bn-rBD/common_strings.xml b/play-services-base/res/values-bn-rBD/common_strings.xml new file mode 100644 index 0000000..90437c6 --- /dev/null +++ b/play-services-base/res/values-bn-rBD/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google পà§à¦²à§‡ পরিষেবার তà§à¦°à§à¦Ÿà¦¿"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"à¦à¦•à¦Ÿà¦¿ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à§‡à¦° জনà§à¦¯ Google পà§à¦²à§‡ পরিষেবার ইনসà§à¦Ÿà¦² করা পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à§·"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"à¦à¦•à¦Ÿà¦¿ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à§‡à¦° জনà§à¦¯ Google পà§à¦²à§‡ পরিষেবার à¦à¦•à¦Ÿà¦¿ আপডেটের পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à§·"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"à¦à¦•à¦Ÿà¦¿ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à§‡à¦° জনà§à¦¯ Android Wear অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à¦Ÿà¦¿à¦° à¦à¦•à¦Ÿà¦¿ আপডেট পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à¥¤"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"à¦à¦•à¦Ÿà¦¿ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à§‡à¦° জনà§à¦¯ Google পà§à¦²à§‡ পরিষেবা সকà§à¦·à¦® করা পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à§·"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> দà§à¦¬à¦¾à¦°à¦¾ অনà§à¦°à§‹à¦§ করা হয়েছে"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google পà§à¦²à§‡ পরিষেবা পান"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Google পà§à¦²à§‡ পরিষেবা ছাড়া à¦à¦‡ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à¦Ÿà¦¿ চলবে না, যেটি আপনার ফোনে অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤à§·"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Google পà§à¦²à§‡ পরিষেবা ছাড়া à¦à¦‡ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à¦Ÿà¦¿ চলবে না, যেটি আপনার টà§à¦¯à¦¾à¦¬à¦²à§‡à¦Ÿà§‡ অনà§à¦ªà¦¸à§à¦¥à¦¿à¦¤à§·"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google পà§à¦²à§‡ পরিষেবা পান"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google পà§à¦²à§‡ পরিষেবা সকà§à¦·à¦® করà§à¦¨"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"আপনি যতকà§à¦·à¦£  না Google পà§à¦²à§‡ পরিষেবা সকà§à¦·à¦® করবেন ততকà§à¦·à¦£ à¦à¦‡ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à¦Ÿà¦¿ চলবে না৷"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google পà§à¦²à§‡ পরিষেবা সকà§à¦·à¦® করà§à¦¨"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google পà§à¦²à§‡ পরিষেবা আপডেট করà§à¦¨"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear আপডেট করà§à¦¨"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"আপনি যতকà§à¦·à¦£ না Google পà§à¦²à§‡ পরিষেবা আপডেট ততকà§à¦·à¦£ à¦à¦‡ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à¦Ÿà¦¿ চলবে না৷"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"আপনি Android Wear অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨ আপডেট না করা পরà§à¦¯à¦¨à§à¦¤ à¦à¦‡ অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨à¦Ÿà¦¿ চলবে না।"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"নেটওয়ারà§à¦• তà§à¦°à§à¦Ÿà¦¿"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google পà§à¦²à§‡ পরিষেবা সংযোগ করতে à¦à¦•à¦Ÿà¦¿ ডেটা সংযোগের পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à§·"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"অবৈধ অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"নিরà§à¦¦à¦¿à¦·à§à¦Ÿ করা অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà¦Ÿà¦¿ ডিà¦à¦¾à¦‡à¦¸à§‡ বিদà§à¦¯à¦®à¦¾à¦¨ নেই৷ দয়া করে à¦à¦•à¦Ÿà¦¿ à¦à¦¿à¦¨à§à¦¨ অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ চয়ন করà§à¦¨à§·"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google পà§à¦²à§‡ পরিষেবার সঙà§à¦—ে অজানা সমসà§à¦¯à¦¾à§·"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google পà§à¦²à§‡ পরিষেবা"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google পà§à¦²à§‡ পরিষেবা, যার উপর আপনার কিছৠঅà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¾à¦¨ নিরà§à¦à¦° করে, আপনার ডিà¦à¦¾à¦‡à¦¸à§‡ সমরà§à¦¥à¦¿à¦¤ নয়৷ দয়া করে সহায়তার জনà§à¦¯ পà§à¦°à¦¸à§à¦¤à§à¦¤à¦•à¦¾à¦°à¦•à§‡à¦° সাথে যোগাযোগ করà§à¦¨à§·"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"আপডেট করà§à¦¨"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"সাইন ইন করà§à¦¨"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google à¦à¦° মাধà§à¦¯à¦®à§‡ সাইন ইন করà§à¦¨"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ফোনে খà§à¦²à§à¦¨"</string> +</resources> diff --git a/play-services-base/res/values-ca/common_strings.xml b/play-services-base/res/values-ca/common_strings.xml new file mode 100644 index 0000000..5b573aa --- /dev/null +++ b/play-services-base/res/values-ca/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Error dels serveis de Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Una aplicació requereix que s\'instal·lin els serveis de Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Una aplicació requereix que s\'actualitzin els serveis de Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Una aplicació necessita que s\'actualitzi l\'aplicació Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Una aplicació requereix que s\'activin els serveis de Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Sol·licitada per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Baixa els serveis de Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Aquesta aplicació no s\'executarà si el telèfon no té instal·lats els serveis de Google Play."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Aquesta aplicació no funcionarà si la tauleta no té instal·lats els serveis de Google Play."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Baixa els serveis de Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activa els serveis de Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aquesta aplicació no funcionarà si no actives els serveis de Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activa els serveis de Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualitza els serveis de Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Actualitza Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Aquesta aplicació no s\'executarà si no actualitzes els serveis de Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Aquesta aplicació no s\'executarà fins que no actualitzis l\'aplicació Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Error de xarxa"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Es requereix una connexió de dades per connectar amb els serveis de Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Compte no và lid"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"El compte especificat no existeix en aquest dispositiu. Tria un compte diferent."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Error desconegut relacionat amb els serveis de Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Serveis de Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"El teu dispositiu no és compatible amb els serveis de Google Play, en què es basen les teves aplicacions. Per obtenir assistència, contacta amb el fabricant."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualitza"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Inicia sessió"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Inicia sessió amb Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Obre al telèfon"</string> +</resources> diff --git a/play-services-base/res/values-cs/common_strings.xml b/play-services-base/res/values-cs/common_strings.xml new file mode 100644 index 0000000..2122219 --- /dev/null +++ b/play-services-base/res/values-cs/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Chyba služeb Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Aplikace vyžaduje instalaci služeb Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Aplikace vyžaduje aktualizaci služeb Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"NÄ›která aplikace vyžaduje aktualizaci aplikace Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Aplikace vyžaduje aktivaci služeb Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Požadováno aplikacà <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Instalovat služby Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ke spuÅ¡tÄ›nà této aplikace jsou potÅ™eba služby Google Play, které v telefonu nemáte."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ke spuÅ¡tÄ›nà této aplikace jsou potÅ™eba služby Google Play, které v tabletu nemáte."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Instalovat služby Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktivovat služby Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ke spuÅ¡tÄ›nà této aplikace je tÅ™eba aktivovat služby Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktivovat služby Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aktualizace služeb Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Aktualizujte aplikaci Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ke spuÅ¡tÄ›nà této aplikace je tÅ™eba aktualizovat služby Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Aplikace bude fungovat po aktualizaci aplikace Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Chyba sÃtÄ›"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"PÅ™ipojenà ke službám Google Play vyžaduje datové pÅ™ipojenÃ."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Neplatný úÄet"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Zadaný úÄet v tomto zaÅ™Ãzenà neexistuje. Zvolte prosÃm jiný úÄet."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nastal neznámý problém se službami Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Služby Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"NÄ›které vaÅ¡e aplikace vyžadujà služby Google Play, které ve vaÅ¡em zaÅ™Ãzenà nejsou podporovány. S žádostà o pomoc se prosÃm obraÅ¥te na výrobce."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualizovat"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"PÅ™ihlásit se"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"PÅ™ihlásit se úÄtem Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"OtevÅ™Ãt v telefonu"</string> +</resources> diff --git a/play-services-base/res/values-da/common_strings.xml b/play-services-base/res/values-da/common_strings.xml new file mode 100644 index 0000000..a3a7c3e --- /dev/null +++ b/play-services-base/res/values-da/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Fejl i Google Play-tjenester"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"En applikation kræver, at Google Play-tjenester installeres."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"En applikation kræver, at Google Play-tjenester opdateres."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"En applikation kræver en opdatering af appen Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"En applikation kræver, at Google Play-tjenester aktiveres."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Anmodning fra <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Hent Google Play-tjenester"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Denne app kan ikke køre uden Google Play-tjenester, som mangler pÃ¥ din telefon."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Denne app kan ikke køre uden Google Play-tjenester, som mangler pÃ¥ din tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Hent Google Play-tjenester"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktivér Google Play-tjenester"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Denne app virker ikke, medmindre du aktiverer Google Play-tjenester."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktivér Google Play-tjenester"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Opdater Google Play-tjenester"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Opdater Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Denne app kan ikke køre, medmindre du opdaterer Google Play-tjenester."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Denne app kan ikke køre, medmindre du opdaterer appen Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netværksfejl"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Der kræves en dataforbindelse for at oprette forbindelse til Google Play-tjenester."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ugyldig konto"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Den angivne konto findes ikke pÃ¥ denne enhed. Vælg en anden konto."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ukendt problem med Google Play-tjenester."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-tjenester"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-tjenester, som nogle af dine applikationer er afhængige af, understøttes ikke af din enhed. Kontakt producenten for at fÃ¥ hjælp."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Opdater"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Log ind"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Log ind med Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ã…bn pÃ¥ telefonen"</string> +</resources> diff --git a/play-services-base/res/values-de/common_strings.xml b/play-services-base/res/values-de/common_strings.xml new file mode 100644 index 0000000..3f05262 --- /dev/null +++ b/play-services-base/res/values-de/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Fehler bei Zugriff auf Google Play-Dienste"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"App erfordert die Installation der Google Play-Dienste"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"App erfordert ein Update der Google Play-Dienste"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Für eine App ist die Aktualisierung der Android Wear App erforderlich."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"App erfordert die Aktivierung der Google Play-Dienste"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Angefordert von <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play-Dienste installieren"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Telefon nicht installiert sind."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Tablet nicht installiert sind."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play-Dienste installieren"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play-Dienste aktivieren"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Diese App funktioniert nur, wenn Sie die Google Play-Dienste aktivieren."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play-Dienste aktivieren"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play-Dienste aktualisieren"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear aktualisieren"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Diese App wird nur ausgeführt, wenn Sie die Google Play-Dienste aktualisieren."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Diese App funktioniert erst nach der Aktualisierung der Android Wear App."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netzwerkfehler"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Um eine Verbindung zu den Google Play-Diensten herzustellen, ist eine Datenverbindung erforderlich."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ungültiges Konto"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Das angegebene Konto ist auf diesem Gerät nicht vorhanden. Bitte wählen Sie ein anderes Konto aus."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Unbekanntes Problem mit Google Play-Diensten"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-Dienste"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-Dienste, auf denen einige Ihrer Apps basieren, werden von diesem Gerät nicht unterstützt. Wenden Sie sich für weitere Informationen an den Hersteller."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualisieren"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Anmelden"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Ãœber Google anmelden"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Auf Telefon öffnen"</string> +</resources> diff --git a/play-services-base/res/values-el/common_strings.xml b/play-services-base/res/values-el/common_strings.xml new file mode 100644 index 0000000..765d0cf --- /dev/null +++ b/play-services-base/res/values-el/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Σφάλμα ΥπηÏεσιών Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Μια εφαÏμογή απαιτεί την εγκατάσταση των ΥπηÏεσιών Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Μια εφαÏμογή απαιτεί την ενημÎÏωση των ΥπηÏεσιών Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Μια εφαÏμογή απαιτεί την ενημÎÏωση της εφαÏμογής Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Μια εφαÏμογή απαιτεί την ενεÏγοποίηση των ΥπηÏεσιών Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Υποβλήθηκε αίτημα από την εφαÏμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Λήψη υπηÏεσιών Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Αυτή η εφαÏμογή δεν θα εκτελεστεί χωÏίς τις υπηÏεσίες Google Play, οι οποίες λείπουν από το τηλÎφωνό σας."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Αυτή η εφαÏμογή δεν θα εκτελεστεί χωÏίς τις υπηÏεσίες Google Play, οι οποίες λείπουν από το tablet σας."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Λήψη υπηÏεσιών Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"ΕνεÏγοποίηση υπηÏεσιών Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Αυτή η εφαÏμογή δεν θα λειτουÏγήσει εάν δεν Îχετε ενεÏγοποιήσει τις υπηÏεσίες Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"ΕνεÏγοπ. υπηÏεσιών Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"ΕνημÎÏωση υπηÏεσιών Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"ΕνημÎÏωση Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Αυτή η εφαÏμογή θα εκτελεστεί Î±Ï†Î¿Ï ÎµÎ½Î·Î¼ÎµÏώσετε τις υπηÏεσίες Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Αυτή η εφαÏμογή δεν θα εκτελεστεί εάν δεν ενημεÏώσετε την εφαÏμογή Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Σφάλμα δικτÏου"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Απαιτείται σÏνδεση δεδομÎνων για να συνδεθείτε με τις ΥπηÏεσίες Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Μη ÎγκυÏος λογαÏιασμός"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Ο συγκεκÏιμÎνος λογαÏιασμός δεν υπάÏχει σε αυτήν τη συσκευή. ΕπιλÎξτε Îναν διαφοÏετικό λογαÏιασμό."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Άγνωστο Ï€Ïόβλημα με τις υπηÏεσίες Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"ΥπηÏεσίες Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Οι υπηÏεσίες Google Play, στις οποίες βασίζονται οÏισμÎνες από τις εφαÏμογÎÏ‚ σας, δεν υποστηÏίζονται στη συσκευή σας. Επικοινωνήστε με τον κατασκευαστή για υποστήÏιξη."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ΕνημÎÏωση"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ΣÏνδεση"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Συνδεθείτε στο Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Άνοιγμα στο τηλÎφωνο"</string> +</resources> diff --git a/play-services-base/res/values-en-rGB/common_strings.xml b/play-services-base/res/values-en-rGB/common_strings.xml new file mode 100644 index 0000000..6beb096 --- /dev/null +++ b/play-services-base/res/values-en-rGB/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play services error"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"An application requires installation of Google Play services."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"An application requires an update for Google Play Services."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"An application requires an update to the Android Wear app."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"An application requires Google Play services to be enabled."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Requested by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Get Google Play services"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"This app won\'t run without Google Play services, which are missing from your phone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"This app won\'t run without Google Play services, which are missing from your tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Get Google Play services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Enable Google Play services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"This app won\'t work unless you enable Google Play services."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Enable Google Play services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Update Google Play services"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Update Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"This app won\'t run unless you update Google Play services."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"This app won\'t run unless you update the Android Wear app."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Network Error"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"A data connection is required to connect to Google Play services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Invalid Account"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"The specified account does not exist on this device. Please choose a different account."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Unknown issue with Google Play services."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Update"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Sign in"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Sign in with Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Open on phone"</string> +</resources> diff --git a/play-services-base/res/values-en-rIN/common_strings.xml b/play-services-base/res/values-en-rIN/common_strings.xml new file mode 100644 index 0000000..6beb096 --- /dev/null +++ b/play-services-base/res/values-en-rIN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play services error"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"An application requires installation of Google Play services."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"An application requires an update for Google Play Services."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"An application requires an update to the Android Wear app."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"An application requires Google Play services to be enabled."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Requested by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Get Google Play services"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"This app won\'t run without Google Play services, which are missing from your phone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"This app won\'t run without Google Play services, which are missing from your tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Get Google Play services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Enable Google Play services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"This app won\'t work unless you enable Google Play services."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Enable Google Play services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Update Google Play services"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Update Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"This app won\'t run unless you update Google Play services."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"This app won\'t run unless you update the Android Wear app."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Network Error"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"A data connection is required to connect to Google Play services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Invalid Account"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"The specified account does not exist on this device. Please choose a different account."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Unknown issue with Google Play services."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Update"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Sign in"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Sign in with Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Open on phone"</string> +</resources> diff --git a/play-services-base/res/values-es-rUS/common_strings.xml b/play-services-base/res/values-es-rUS/common_strings.xml new file mode 100644 index 0000000..853d4f2 --- /dev/null +++ b/play-services-base/res/values-es-rUS/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Error de Google Play Services"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Una aplicación requiere que se instale Google Play Services"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Una aplicación requiere que se actualice Google Play Services"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Hay una aplicación que requiere una actualización para la aplicación Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Una aplicación requiere que se habilite Google Play Services"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Solicitada por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Obtener Google Play Services"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicación no se ejecutará si no instalasGoogle Play Services en tu dispositivo."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicación no se ejecutará si no instalas Google Play Services en tu tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Descargar Google Play Services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activar Google Play Services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicación no funcionará si no activas Google Play Services."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activar Google Play Services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualizar Google Play Services"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Actualizar Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicación no se ejecutará si no actualizas Google Play Services."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Esta aplicación no se ejecutará, a menos que actualices la aplicación Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Error de red"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Se necesita una conexión de datos para establecer conexión con Google Play Services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Cuenta no válida"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"La cuenta especificada no existe en este dispositivo. Elige otra cuenta."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Error desconocido relacionado con Google Play Services"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play Services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play Services, del cual dependen algunas de tus aplicaciones, no es compatible con tu dispositivo. ComunÃcate con el fabricante para obtener ayuda."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualizar"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Acceder"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Acceder con Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Abrir en el teléfono"</string> +</resources> diff --git a/play-services-base/res/values-es/common_strings.xml b/play-services-base/res/values-es/common_strings.xml new file mode 100644 index 0000000..ba28fe2 --- /dev/null +++ b/play-services-base/res/values-es/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Error de servicios de Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Una aplicación requiere la instalación de servicios de Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Una aplicación requiere una actualización de servicios de Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Una aplicación necesita que Android Wear se actualice."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Una aplicación requiere que se habiliten los servicios de Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Solicitada por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Descargar servicios de Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicación no se ejecutará si tu teléfono no tiene instalados los servicios de Google Play."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicación no se ejecutará si tu tablet no tiene instalados los servicios de Google Play."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Descargar servicios de Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Habilitar servicios de Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicación no funcionará si no habilitas los servicios de Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Habilitar servicios de Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualizar servicios de Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Actualizar Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicación no se ejecutará si no actualizas los servicios de Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Esta aplicación no se ejecutará hasta que actualices Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Error de red"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Se necesita una conexión de datos para establecer conexión con los servicios de Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Cuenta no válida"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"La cuenta especificada no existe en este dispositivo. Selecciona otra cuenta."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Error desconocido relacionado con los servicios de Google Play"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Servicios de Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Tu dispositivo no es compatible con los servicios de Google Play, de los cuales dependen tus aplicaciones. Para obtener asistencia, ponte en contacto el fabricante."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualizar"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Iniciar sesión"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Iniciar sesión con Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Abrir en teléfono"</string> +</resources> diff --git a/play-services-base/res/values-et-rEE/common_strings.xml b/play-services-base/res/values-et-rEE/common_strings.xml new file mode 100644 index 0000000..603068f --- /dev/null +++ b/play-services-base/res/values-et-rEE/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Viga Google Play teenustes"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Rakenduse kasutamiseks peavad olema installitud Google Play teenused."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Rakenduse kasutamiseks tuleb värskendada Google Play teenuseid."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Rakendus nõuab rakenduse Android Wear värskendamist."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Rakenduse kasutamiseks peavad olema lubatud Google Play teenused."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Taotluse esitas <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Hankige Google Play teenused"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie telefonis pole."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie tahvelarvutis pole."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Hankige Google Play teenused"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Lubage Google Play teenused"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"See rakendus ei tööta, kui te ei luba Google Play teenuseid."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Lubage Google Play teenused"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Värskendage Google Play teenuseid"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Rakenduse Android Wear värskendamine"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Seda rakendust ei saa käitada, kui te ei värskenda Google Play teenuseid."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Rakendus töötab ainult siis, kui värskendate rakendust Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Võrgu viga"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play teenustega ühenduse loomiseks on vajalik andmesideühendus."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Vale konto"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Määratud kontot pole selles seadmes olemas. Valige muu konto."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play teenuste tundmatu probleem."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play teenused"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Teie seade ei toeta Google Play teenuseid, millele mõni teie rakendustest toetub. Abi saamiseks võtke ühendust tootjaga."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Värskenda"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Logi sisse"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Logi sisse Google\'iga"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ava telefonis"</string> +</resources> diff --git a/play-services-base/res/values-eu-rES/common_strings.xml b/play-services-base/res/values-eu-rES/common_strings.xml new file mode 100644 index 0000000..189bfa7 --- /dev/null +++ b/play-services-base/res/values-eu-rES/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play zerbitzuen errorea"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Aplikazio batek Google Play zerbitzuak instalatzea eskatzen du."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Aplikazio batek Google Play zerbitzuak eguneratzea eskatzen du."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Aplikazio batek Android Wear eguneratzea eskatzen du."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Aplikazio batek Google Play zerbitzuak gaituta egotea eskatzen du."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak eskatu du"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Lortu Google Play zerbitzuak"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Aplikazio hau ez da exekutatuko Google Play zerbitzurik gabe, baina horiek ez daude telefonoan."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Aplikazio hau ez da exekutatuko Google Play zerbitzurik gabe, baina horiek ez daude tabletan."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Lortu Google Play zerbitzuak"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Gaitu Google Play zerbitzuak"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aplikazio honek ez du funtzionatuko Google Play zerbitzuak gaitzen ez badituzu."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Gaitu Google Play zerbitzuak"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Eguneratu Google Play zerbitzuak"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Eguneratu Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Aplikazio hau ez da exekutatuko Google Play zerbitzuak eguneratzen ez badituzu."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Aplikazio hau ez da exekutatuko Android Wear aplikazioa eguneratu ezean."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Sareko errorea"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Datu-konexioa behar da Google Play zerbitzuetara konektatzeko."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Kontu baliogabea"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Zehaztutako kontua ez dago gailuan. Aukeratu beste kontu bat."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play zerbitzuekin arazo ezezaguna dago."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play zerbitzuak"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Aplikazioetako batzuek behar dituzten Google Play zerbitzuak ez dira zure gailuan onartzen. Laguntza lortzeko, jarri fabrikatzailearen harremanetan."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Eguneratu"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Hasi saioa"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Hasi saioa Google-n"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ireki telefonoan"</string> +</resources> diff --git a/play-services-base/res/values-fa/common_strings.xml b/play-services-base/res/values-fa/common_strings.xml new file mode 100644 index 0000000..6de54d6 --- /dev/null +++ b/play-services-base/res/values-fa/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"â€Ø®Ø·Ø§ در خدمات Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"â€Ø¨Ø±Ù†Ø§Ù…ه‌ای نیاز به نصب خدمات Google Play دارد."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"â€â€«Ø¨Ø±Ù†Ø§Ù…ه‌ای نیاز به یک به‌روزرسانی برای خدمات Google Play دارد."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"â€Ø¨Ø±Ù†Ø§Ù…Ù‡ باید به برنامه Android Wear به‌روزرسانی شود."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"â€Ø¨Ø±Ù†Ø§Ù…ه‌ای نیاز به Ùعال شدن خدمات Google Play دارد."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"درخواست توسط <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"â€Ø¯Ø±ÛŒØ§Ùت خدمات Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"â€Ø§ÛŒÙ† برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در تلÙÙ† شما وجود ندارد."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"â€Ø§ÛŒÙ† برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در رایانهٔ لوØÛŒ شما وجود ندارد."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"â€Ø¯Ø±ÛŒØ§Ùت خدمات Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"â€Ùعال کردن خدمات Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"â€ØªØ§ زمانی‌که خدمات Google Play را Ùعال نکنید این برنامه کار نمی‌کند."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"â€Ùعال کردن خدمات Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"â€Ø¨Ù‡â€ŒØ±ÙˆØ²Ø±Ø³Ø§Ù†ÛŒ خدمات Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"â€Ø¨Ù‡â€ŒØ±ÙˆØ²Ø±Ø³Ø§Ù†ÛŒ Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"â€ØªØ§ زمانی‌که خدمات Google Play را به‌روز نکنید این برنامه کار نمی‌کند."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"â€Ø§ÛŒÙ† برنامه اجرا نمی‌شود مگر اینکه برنامه Android Wear را به‌روزرسانی کنید."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"خطای شبکه"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"â€Ø¨Ø±Ø§ÛŒ اتصال به خدمات Google Play اتصال داده لازم است."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Øساب نامعتبر"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Øسابی Ú©Ù‡ تعیین کردید در این دستگاه وجود ندارد. لطÙاً Øساب دیگری را انتخاب کنید."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"â€Ù…Ø´Ú©Ù„ نامشخص در خدمات Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"â€Ø®Ø¯Ù…ات Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"â€Ø®Ø¯Ù…ات Google PlayØŒ Ú©Ù‡ برخی از برنامه‌های شما به آن وابسته است، توسط دستگاه شما پشتیبانی نمی‌شود. لطÙاً برای دریاÙت Ú©Ù…Ú© با سازنده تماس بگیرید."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"به‌روزرسانی"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ورود به سیستم"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"â€ÙˆØ±ÙˆØ¯ به سیستم با Google‎"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"باز کردن در تلÙÙ†"</string> +</resources> diff --git a/play-services-base/res/values-fi/common_strings.xml b/play-services-base/res/values-fi/common_strings.xml new file mode 100644 index 0000000..9b96f49 --- /dev/null +++ b/play-services-base/res/values-fi/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Virhe Google Play -palveluissa"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Asenna Google Play -palvelut, jotta sovellus toimii."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Päivitä Google Play -palvelut, jotta sovellus toimii."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android Wear -sovellus täytyy päivittää toisen sovelluksen takia."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ota käyttöön Google Play -palvelut, jotta sovellus toimii."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Pyynnön teki <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Asenna Google Play -palvelut"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat puhelimesta."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat tablet-laitteesta."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Asenna Google Play -palvelut"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ota Google Play -palvelut käyttöön"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Tämä sovellus ei toimi, ellet ota Google Play -palveluita käyttöön."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ota Google Play -palv. käyttöön"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Päivitä Google Play -palvelut"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Päivitä Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Tämä sovellus ei toimi, ellet päivitä Google Play -palveluita."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Tämä sovellus ei toimi, ellet päivitä Android Wear -sovellusta."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Verkkovirhe"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play -palveluiden käyttöön tarvitaan tietoliikenneyhteys."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Tili ei kelpaa"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Kyseistä tiliä ei ole tällä laitteella. Valitse toinen tili."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Tuntematon ongelma käytettäessä Google Play -palveluita."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play -palvelut"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play -palveluita, joita osa sovelluksistasi käyttää, ei tueta laitteellasi. Pyydä ohjeita laitteen valmistajalta."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Päivitä"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Kirjaudu"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Kirjaudu Google-tiliin"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Avaa puhelimessa"</string> +</resources> diff --git a/play-services-base/res/values-fr-rCA/common_strings.xml b/play-services-base/res/values-fr-rCA/common_strings.xml new file mode 100644 index 0000000..9ddaded --- /dev/null +++ b/play-services-base/res/values-fr-rCA/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Erreur liée aux services Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Une application demande l\'installation des services Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Une application requiert la mise à jour des services Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Une application nécessite une mise à jour d\'Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Une application requiert l\'activation des services Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Demandée par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installer les services Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installer les services Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activer les services Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activer les services Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Mettre à jour les services Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Mettre à jour Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour l\'application Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erreur réseau"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Vous devez disposer d\'une connexion de données pour utiliser les services Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Compte erroné"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Le compte indiqué n\'existe pas sur cet appareil. Veuillez sélectionner un autre compte."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problème inconnu avec les services Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Services Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Mettre à jour"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Connexion"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Se connecter via Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ouvrir sur le téléphone"</string> +</resources> diff --git a/play-services-base/res/values-fr/common_strings.xml b/play-services-base/res/values-fr/common_strings.xml new file mode 100644 index 0000000..d993858 --- /dev/null +++ b/play-services-base/res/values-fr/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Erreur liée aux services Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Une application demande l\'installation des services Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Une application demande la mise à jour des services Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Une application nécessite une mise à jour du Bios de l\'application Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Une application demande l\'activation des services Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Notification issue de l\'application \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installer les services Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installer services Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activer les services Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activer services Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Mettre à jour les services Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Mettre à jour Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour l\'application Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erreur réseau"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Vous devez disposer d\'une connexion de données pour utiliser les services Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Compte erroné"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Le compte indiqué n\'existe pas sur cet appareil. Veuillez sélectionner un autre compte."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problème inconnu avec les services Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Services Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Mettre à jour"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Connexion"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Se connecter avec Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ouvrir sur le téléphone"</string> +</resources> diff --git a/play-services-base/res/values-gl-rES/common_strings.xml b/play-services-base/res/values-gl-rES/common_strings.xml new file mode 100644 index 0000000..8f35507 --- /dev/null +++ b/play-services-base/res/values-gl-rES/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Erro nos servizos de Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"As aplicacións requiren a instalación dos servizos de Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Unha aplicación require a actualización dos servizos de Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Unha aplicación require unha actualización da aplicación Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"As aplicacións requiren ter os servizos de Google Play activados."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Solicitado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Descargar servizos de Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicación non se executará se o teléfono non ten instalados os servizos de Google Play."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicación non se executará se o tablet non ten instalados os servizos de Google Play."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Obter servizos de Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Activar servizos de Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicación non funcionará se non activas os servizos de Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Activar servizos de Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Actualizar os servizos de Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Actualizar Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicación non se executará se non actualizas os servizos de Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Esta aplicación non se executará se non actualizas a aplicación Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro de rede"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necesario dispoñer dunha conexión de datos para conectarse aos servizos de Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta non válida"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada non existe neste dispositivo. Escolle unha diferente."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Erro descoñecido cos servizos de Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Servizos de Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Os servizos de Google Play, nos que confÃan algunhas das túas aplicacións, non son compatibles co teu dispositivo. Ponte en contacto co fabricante para obter asistencia."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Actualizar"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Iniciar sesión"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Iniciar sesión con Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Abrir no teléfono"</string> +</resources> diff --git a/play-services-base/res/values-hi/common_strings.xml b/play-services-base/res/values-hi/common_strings.xml new file mode 100644 index 0000000..5edabf2 --- /dev/null +++ b/play-services-base/res/values-hi/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play सेवाà¤à¤‚ तà¥à¤°à¥à¤Ÿà¤¿"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के लिठGoogle Play सेवाà¤à¤‚ इंसà¥à¤Ÿà¥‰à¤² किठजाने की आवशà¥à¤¯à¤•à¤¤à¤¾ है."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के लिठGoogle Play सेवाओं में नई जानकारी की आवशà¥à¤¯à¤•à¤¤à¤¾ है."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ को Android Wear à¤à¤ªà¥à¤¸ में अपडेट की आवशà¥à¤¯à¤•à¤¤à¤¾ है."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के लिठGoogle Play सेवाà¤à¤‚ सकà¥à¤·à¤® किठजाने की आवशà¥à¤¯à¤•à¤¤à¤¾ है."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> के दà¥à¤µà¤¾à¤°à¤¾ अनà¥à¤°à¥‹à¤§à¤¿à¤¤"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play सेवाà¤à¤‚ पाà¤à¤‚"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"यह à¤à¤ªà¥à¤¸ Google Play सेवाओं के बिना नहीं चलेगा, जो आपके फ़ोन में नहीं हैं."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"यह à¤à¤ªà¥à¤¸ Google Play सेवाओं के बिना नहीं चलेगा, जो आपके टेबलेट में नहीं हैं."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play सेवाà¤à¤‚ पाà¤à¤‚"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play सेवाà¤à¤‚ सकà¥à¤·à¤® करें"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"जब तक आप Google Play सेवाà¤à¤‚ सकà¥à¤·à¤® नहीं करते, तब तक यह à¤à¤ªà¥à¤¸ कारà¥à¤¯ नहीं करेगा."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play सेवाà¤à¤‚ सकà¥à¤·à¤® करें"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play सेवाà¤à¤‚ से नई जानकारी"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear अपडेट करें"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"जब तक आप Google Play सेवाओं से नई जानकारी नहीं लेते हैं, तब तक यह à¤à¤ªà¥à¤¸ नहीं चलेगा."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"यह à¤à¤ªà¥à¤¸ तब तक नहीं चलेगा, जब तक कि आप Android Wear à¤à¤ªà¥à¤¸ को अपडेट नहीं करते."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"नेटवरà¥à¤• तà¥à¤°à¥à¤Ÿà¤¿"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play सेवाओं से कनेकà¥à¤Ÿ करने के लिठडेटा कनेकà¥à¤¶à¤¨ की आवशà¥à¤¯à¤•à¤¤à¤¾ है."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"अमानà¥à¤¯ खाता"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ खाता इस डिवाइस पर मौजूद नहीं है. कृपया कोई à¤à¤¿à¤¨à¥à¤¨ खाता चà¥à¤¨à¥‡à¤‚."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play सेवाओं के साथ अजà¥à¤žà¤¾à¤¤ समसà¥à¤¯à¤¾."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play सेवाà¤à¤‚"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play सेवाà¤à¤‚, जिन पर आपके कà¥à¤› à¤à¤ªà¥à¤¸ निरà¥à¤à¤° करते हैं, आपके डिवाइस दà¥à¤µà¤¾à¤°à¤¾ समरà¥à¤¥à¤¿à¤¤ नहीं हैं. कृपया सहायता के लिठनिरà¥à¤®à¤¾à¤¤à¤¾ से संपरà¥à¤• करें."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"नई जानकारी पाà¤à¤‚"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"पà¥à¤°à¤µà¥‡à¤¶ करें"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google से पà¥à¤°à¤µà¥‡à¤¶ करें"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"फ़ोन पर खोलें"</string> +</resources> diff --git a/play-services-base/res/values-hr/common_strings.xml b/play-services-base/res/values-hr/common_strings.xml new file mode 100644 index 0000000..49e1daf --- /dev/null +++ b/play-services-base/res/values-hr/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"PogreÅ¡ka Usluga za Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Aplikacija zahtijeva instaliranje Usluga za Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Aplikacija zahtijeva ažuriranje Usluga za Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Aplikacija zahtijeva ažuriranje na aplikaciju Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Aplikacija zahtijeva da Usluge za Google Play budu omogućene."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Zahtijeva aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Preuzmi usluge za Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vaÅ¡em telefonu."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vaÅ¡em tabletnom raÄunalu."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Preuzmi usluge za Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Omogući usluge za Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ova aplikacija neće raditi ako ne omogućite usluge za Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Omogući usluge za Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ažuriraj usluge za Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Ažurirajte Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ova se aplikacija neće pokrenuti ako ne ažurirate usluge za Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ova aplikacija neće funkcionirati ako ne ažurirate aplikaciju Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Mrežna pogreÅ¡ka"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Potrebna je podatkovna veza za povezivanje s uslugama Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Nevažeći raÄun"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Navedeni raÄun ne postoji na ovom ureÄ‘aju. Odaberite neki drugi raÄun."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nepoznata poteÅ¡koća s uslugama za Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Usluge za Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Usluge za Google Play, koje su potrebne za funkcioniranje nekih vaÅ¡ih aplikacija, nisu podržane na vaÅ¡em ureÄ‘aju. Pomoć potražite od proizvoÄ‘aÄa."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ažuriranje"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Prijava"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prijava uslugom Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Otvaranje na telefonu"</string> +</resources> diff --git a/play-services-base/res/values-hu/common_strings.xml b/play-services-base/res/values-hu/common_strings.xml new file mode 100644 index 0000000..7f57e27 --- /dev/null +++ b/play-services-base/res/values-hu/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play-szolgáltatások – hiba"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Egy alkalmazás Google Play-szolgáltatások telepÃtését kéri."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Egy alkalmazás Google Play-szolgáltatások frissÃtését kéri."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Egy alkalmazás az Android Wear-alkalmazás frissÃtését igényli."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Egy alkalmazás Google Play-szolgáltatások engedélyezését kéri."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> kérésére"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Play-szolgáltatások telepÃtése"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Az alkalmazás működéséhez a Google Play-szolgáltatások szükségesek, ezek nincsenek telepÃtve a telefonon."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Az alkalmazás működéséhez a Google Play-szolgáltatások szükségesek, ezek nincsenek telepÃtve a táblagépen."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Play-szolgáltatások telepÃtése"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play-szolgáltatások aktiválása"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Az alkalmazás csak akkor fog működni, ha engedélyezi a Google Play-szolgáltatásokat."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Play-szolgáltatások aktiválása"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Play-szolgáltatások frissÃtése"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Az Android Wear frissÃtése"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Az alkalmazás csak akkor fog működni, ha frissÃti a Google Play-szolgáltatásokat."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ez az alkalmazás nem működik, amÃg nem frissÃti az Android Wear-alkalmazást."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Hálózati hiba"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"A Google Play-szolgáltatásokhoz történÅ‘ kapcsolódáshoz adatkapcsolat szükséges."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Érvénytelen fiók"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A megadott fiók nem létezik ezen az eszközön. Kérjük, válasszon másik fiókot."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ismeretlen hiba a Google Play-szolgáltatásokban."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-szolgáltatások"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"A Google Play-szolgáltatásokat, amelyre egyes alkalmazások támaszkodnak, nem támogatja az eszköz. SegÃtségért forduljon az eszköz gyártójához."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"FrissÃtés"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Belépés"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google-bejelentkezés"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Megnyitás a telefonon"</string> +</resources> diff --git a/play-services-base/res/values-hy-rAM/common_strings.xml b/play-services-base/res/values-hy-rAM/common_strings.xml new file mode 100644 index 0000000..a88c957 --- /dev/null +++ b/play-services-base/res/values-hy-rAM/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ½ÕÕ¡Õ¬ Õ¯Õ¡"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Ô»Õ¶Õ¹-Õ¸Ö€ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´ Õ§ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨:"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Ô»Õ¶Õ¹-Õ¸Ö€ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´ Õ§ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨:"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ô¾Ö€Õ¡Õ£Õ«Ö€Õ¨ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´ Õ§ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Android Wear-Õ¨:"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ô»Õ¶Õ¹-Õ¸Ö€ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´ Õ§ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨:"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g>-Õ« Õ°Õ¡Ö€ÖÕ´Õ¡Õ´Õ¢"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"ÕÕ¥Õ²Õ¡Õ¤Ö€Õ¥Ö„ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ô±ÕµÕ½ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ Õ¹Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¾Õ« Õ¡Õ¼Õ¡Õ¶Ö Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ«, Õ¸Ö€Õ¸Õ¶Ö„ Õ¢Õ¡ÖÕ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´ Õ¥Õ¶ Õ±Õ¥Ö€ Õ°Õ¥Õ¼Õ¡ÕÕ¸Õ½Õ¸Ö‚Õ´:"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ô±ÕµÕ½ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ Õ¹Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¾Õ« Õ¡Õ¼Õ¡Õ¶Ö Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ«, Õ¸Ö€Õ¸Õ¶Ö„ Õ¢Õ¡ÖÕ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´ Õ¥Õ¶ Õ±Õ¥Ö€ Õ£Ö€Õ¡Õ½Õ¡Õ¬Õ«Õ¯Õ¸Ö‚Õ´:"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"ÕÕ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ô±ÕµÕ½ Õ®Ö€Õ¡Õ£Õ«Ö€Õ¨ Õ¹Õ« Õ¡Õ·ÕÕ¡Õ¿Õ«, Õ¥Õ©Õ¥ Õ¤Õ¸Ö‚Ö„ Õ¹Õ´Õ«Õ¡ÖÕ¶Õ¥Ö„ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨:"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Õ†Õ¸Ö€Õ¡ÖÖ€Õ¥Ö„ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Android Wear-Õ¨"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ô±ÕµÕ½ Õ®Ö€Õ¡Õ£Õ«Ö€Õ¨ Õ¹Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¾Õ«, Õ¥Õ©Õ¥ Õ¤Õ¸Ö‚Ö„ Õ¹Õ¶Õ¸Ö€Õ¡ÖÕ¶Õ¥Ö„ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨:"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ô±ÕµÕ½ Õ®Ö€Õ¡Õ£Õ«Ö€Õ¨ Õ¹Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¾Õ«, Õ¥Õ©Õ¥ Õ¹Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Ö„ Android Wear-Õ¨:"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Õ‘Õ¡Õ¶ÖÕ« Õ½ÕÕ¡Õ¬ Õ¯Õ¡"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ÕŠÕ¡Õ°Õ¡Õ¶Õ»Õ¾Õ¸Ö‚Õ´ Õ§ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¯Õ¡Õº` Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€:"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Õ€Õ¡Õ·Õ«Õ¾Õ¶ Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ§"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Õ†Õ·Õ¾Õ¡Õ® Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ« Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´: Ô¸Õ¶Õ¿Ö€Õ¥Ö„ Õ¡ÕµÕ¬ Õ°Õ¡Õ·Õ«Õ¾:"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ô±Õ¶Õ°Õ¡ÕµÕ¿ ÕÕ¶Õ¤Õ«Ö€Õ Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¸Ö‚Õ´:"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨, Õ¸Ö€Õ¸Õ¶Ö Õ¡ÕºÕ¡Õ¾Õ«Õ¶Õ¸Ö‚Õ´ Õ¥Õ¶ Õ±Õ¥Ö€ Õ®Ö€Õ¡Õ£Ö€Õ¥Ö€Õ«Ö Õ¸Ö€Õ¸Õ·Õ¶Õ¥Ö€Õ¨, Õ¹Õ¥Õ¶ Õ¡Õ»Õ¡Õ¯ÖÕ¾Õ¸Ö‚Õ´ Õ±Õ¥Ö€ Õ½Õ¡Ö€Ö„Õ« Õ¯Õ¸Õ²Õ´Õ«Ö: Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¯Õ¡ÕºÕ¾Õ¥Õ¬ Õ¡Ö€Õ¿Õ¡Õ¤Ö€Õ¸Õ²Õ« Õ°Õ¥Õ¿ Ö…Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€:"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Õ†Õ¸Ö€Õ¡ÖÕ¶Õ¥Õ¬"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Õ„Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Õ„Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Ö„ Google-Õ¸Õ¾"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ô²Õ¡ÖÕ¥Õ¬ Õ°Õ¥Õ¼Õ¡ÕÕ¸Õ½Õ¸Ö‚Õ´"</string> +</resources> diff --git a/play-services-base/res/values-in/common_strings.xml b/play-services-base/res/values-in/common_strings.xml new file mode 100644 index 0000000..d2c3df5 --- /dev/null +++ b/play-services-base/res/values-in/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Kesalahan layanan Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Aplikasi mewajibkan pemasangan layanan Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Aplikasi mewajibkan pembaruan untuk layanan Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Aplikasi memerlukan pembaruan ke aplikasi Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Aplikasi mewajibkan agar layanan Google Play diaktifkan."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Diminta oleh <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Dapatkan layanan Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di ponsel Anda."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di tablet Anda."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Dapatkan layanan Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktifkan layanan Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aplikasi ini tidak akan bekerja sampai Anda mengaktifkan layanan Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktifkan layanan Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Perbarui layanan Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Perbarui Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Aplikasi ini tidak akan berjalan sampai Anda memperbarui layanan Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Aplikasi ini tidak akan berjalan sampai Anda memperbarui layanan Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Kesalahan Jaringan"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Sambungan data diperlukan untuk tersambung ke layanan Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Akun Tidak Valid"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Akun yang ditentukan tidak ada di perangkat ini. Pilih akun lain."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Masalah tidak diketahui pada layanan Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Layanan Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Layanan Google Play, yang diandalkan oleh beberapa aplikasi Anda, tidak didukung oleh perangkat Anda. Hubungi pabrikan untuk mendapatkan bantuan."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Perbarui"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Masuk"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Masuk dengan Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Buka di ponsel"</string> +</resources> diff --git a/play-services-base/res/values-is-rIS/common_strings.xml b/play-services-base/res/values-is-rIS/common_strings.xml new file mode 100644 index 0000000..00975b7 --- /dev/null +++ b/play-services-base/res/values-is-rIS/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Villa à þjónustu Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Forrit krefst þess að þjónusta Google Play sé sett upp."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Forrit krefst þess að þjónusta Google Play sé uppfærð."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Forrit krefst uppfærslu á Android Wear forritinu."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Forrit krefst þess að þjónusta Google Play sé virk."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> bað um"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Sækja þjónustu Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Þetta forrit getur ekki keyrt án þjónustu Google Play, sem vantar à sÃmann þinn."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Þetta forrit getur ekki keyrt án þjónustu Google Play, sem vantar à spjaldtölvuna þÃna."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Sækja þjónustu Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Virkja þjónustu Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Þetta forrit virkar ekki nema þú gerir þjónustu Google Play virka."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Virkja þjónustu Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Uppfæra þjónustu Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Uppfærðu Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Þetta forrit getur ekki keyrt nema þú uppfærir þjónustu Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Þetta forrit getur ekki keyrt nema þú uppfærir Android Wear forritið."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netvilla"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Gagnatengingar er krafist til að tengjast þjónustu Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ógildur reikningur"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Tilgreindur reikningur er ekki til staðar à þessu tæki. Veldu annan reikning."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Óþekkt vandamál með þjónustu Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Þjónusta Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Þjónusta Google Play, sem sum forrit reiða sig á, er ekki studd à tækinu þÃnu. Hafðu samband við framleiðandann til að fá aðstoð."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Uppfæra"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Skrá inn"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Skrá inn með Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Opna à sÃmanum"</string> +</resources> diff --git a/play-services-base/res/values-it/common_strings.xml b/play-services-base/res/values-it/common_strings.xml new file mode 100644 index 0000000..d88b4c6 --- /dev/null +++ b/play-services-base/res/values-it/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Errore Google Play Services"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Un\'applicazione richiede l\'installazione di Google Play Services."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Un\'applicazione richiede un aggiornamento di Google Play Services."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Un\'applicazione richiede l\'aggiornamento dell\'app Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Un\'applicazione richiede l\'attivazione di Google Play Services."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Richiesta da <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installa Google Play Services"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"L\'app non funzionerà senza Google Play Services, non presente sul tuo telefono."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"L\'app non funzionerà senza Google Play Services, non presente sul tuo tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installa Google Play Services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Attiva Google Play Services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"L\'app non funzionerà se non attivi Google Play Services."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Attiva Google Play Services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aggiorna Google Play Services"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Aggiorna Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"L\'app non funzionerà se non aggiorni Google Play Services."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Questa app funzionerà solo dopo avere aggiornato Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Errore di rete"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"È necessaria una connessione dati per connettersi a Google Play Services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Account non valido"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"L\'account specificato non esiste su questo dispositivo. Scegli un altro account."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema sconosciuto con Google Play Services."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play Services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"La piattaforma Google Play Services, su cui sono basate alcune delle tue applicazioni, non è supportata dal dispositivo in uso. Per assistenza, contatta il produttore."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aggiorna"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Accedi"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Accedi con Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Apri sul telefono"</string> +</resources> diff --git a/play-services-base/res/values-iw/common_strings.xml b/play-services-base/res/values-iw/common_strings.xml new file mode 100644 index 0000000..67519b4 --- /dev/null +++ b/play-services-base/res/values-iw/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"â€×©×’×™××” בשירותי Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"â€×§×™×™×ž×ª ×פליקציה המחייבת ×”×ª×§× ×” של שירותי Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"â€×§×™×™×ž×ª ×פליקציה המחייבת עדכון עבור שירותי Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"â€×פליקציה מסוימת דורשת עדכון ל×פליקציה Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"â€×§×™×™×ž×ª ×פליקציה המחייבת הפעלה של שירותי Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"התבקשה על ידי <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"â€×§×‘ל ×ת שירותי Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"â€×פליקציה זו ×œ× ×ª×¤×¢×œ ×œ×œ× ×©×™×¨×•×ª×™ Google Play, ×”×—×¡×¨×™× ×‘×˜×œ×¤×•×Ÿ שלך."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"â€×פליקציה זו ×œ× ×ª×¤×¢×œ ×œ×œ× ×©×™×¨×•×ª×™ Google Play, ×”×—×¡×¨×™× ×‘×˜×בלט שלך."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"â€×§×‘ל ×ת שירותי Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"â€×”פעלת שירותי Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"â€×פליקציה זו ×œ× ×ª×¢×‘×•×“ ×× ×œ× ×ª×¤×¢×™×œ ×ת שירותי Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"â€×”פעל ×ת שירותי Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"â€×¢×“כון שירותי Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"â€×¢×“כון Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"â€×פליקציה זו ×œ× ×ª×¤×¢×œ ×× ×œ× ×ª×¢×“×›×Ÿ ×ת שירותי Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"â€×פליקציה זו ×œ× ×ª×¤×¢×œ עד שתעדכן ×ת ×”×פליקציה Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"שגי×ת רשת."</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"â€×“רוש חיבור × ×ª×•× ×™× ×›×“×™ להתחבר לשירותי Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"חשבון ×œ× ×—×•×§×™"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"החשבון שצוין ×œ× ×§×™×™× ×‘×ž×›×©×™×¨ ×–×”. בחר חשבון ×חר."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"â€×‘×¢×™×” ×œ× ×™×“×•×¢×” בשירותי Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"â€×©×™×¨×•×ª×™ Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"â€×©×™×¨×•×ª×™ Google Play, שחלק מה×פליקציות שלך מתבססות עליה×, ××™× × × ×ª×ž×›×™× ×¢×œ ידי המכשיר שברשותך. צור קשר ×¢× ×”×™×¦×¨×Ÿ לקבלת סיוע."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"עדכן"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"×”×™×›× ×¡"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"â€×”×™×›× ×¡ ב×מצעות Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"פתח בטלפון"</string> +</resources> diff --git a/play-services-base/res/values-ja/common_strings.xml b/play-services-base/res/values-ja/common_strings.xml new file mode 100644 index 0000000..d8a928b --- /dev/null +++ b/play-services-base/res/values-ja/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play開発者サービスã®ã‚¨ãƒ©ãƒ¼"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"アプリã§ã¯Google Play開発者サービスをインストールã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"アプリã§ã¯Google Play開発者サービスを更新ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android Wearアプリã®æ›´æ–°ãŒå¿…è¦ã§ã™ã€‚"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"アプリã§ã¯Google Play開発者サービスを有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g>ã«ã‚ˆã‚‹ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Play開発者サービスã®å…¥æ‰‹"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ã“ã®ã‚¢ãƒ—リã®å®Ÿè¡Œã«ã¯Google Play開発者サービスãŒå¿…è¦ã§ã™ãŒã€ãŠä½¿ã„ã®æºå¸¯ç«¯æœ«ã«ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ã“ã®ã‚¢ãƒ—リã®å®Ÿè¡Œã«ã¯Google Play開発者サービスãŒå¿…è¦ã§ã™ãŒã€ãŠä½¿ã„ã®ã‚¿ãƒ–レットã«ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã›ã‚“。"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Play開発者サービスã®å…¥æ‰‹"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Play開発者サービスã®æœ‰åŠ¹åŒ–"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"ã“ã®ã‚¢ãƒ—リã®å®Ÿè¡Œã«ã¯ã€Google Play開発者サービスã®æœ‰åŠ¹åŒ–ãŒå¿…è¦ã§ã™ã€‚"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Play開発者サービスã®æœ‰åŠ¹åŒ–"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Play開発者サービスã®æ›´æ–°"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wearã®æ›´æ–°"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"ã“ã®ã‚¢ãƒ—リã®å®Ÿè¡Œã«ã¯ã€Google Play開発者サービスã®æ›´æ–°ãŒå¿…è¦ã§ã™ã€‚"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android Wearアプリを使用ã™ã‚‹ã«ã¯ã‚¢ãƒ—リã®æ›´æ–°ãŒå¿…è¦ã§ã™ã€‚"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¨ãƒ©ãƒ¼"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play開発者サービスã«æŽ¥ç¶šã™ã‚‹ã«ã¯ã€ãƒ‡ãƒ¼ã‚¿æŽ¥ç¶šãŒå¿…è¦ã§ã™ã€‚"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"無効ãªã‚¢ã‚«ã‚¦ãƒ³ãƒˆ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"指定ã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ã“ã®ç«¯æœ«ä¸Šã«å˜åœ¨ã—ã¾ã›ã‚“。別ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’é¸æŠžã—ã¦ãã ã•ã„。"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play開発者サービスã§åŽŸå› ä¸æ˜Žã®å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play開発者サービス"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"一部ã®ã‚¢ãƒ—リãŒä½¿ç”¨ã—ã¦ã„ã‚‹Google Play開発者サービスã¯ã€ãŠä½¿ã„ã®ç«¯æœ«ã§ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。詳ã—ãã¯ã€ç«¯æœ«ãƒ¡ãƒ¼ã‚«ãƒ¼ã¾ã§ãŠå•ã„åˆã‚ã›ãã ã•ã„。"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"æ›´æ–°"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ãƒã‚°ã‚¤ãƒ³"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Googleã§ãƒã‚°ã‚¤ãƒ³"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"端末ã§é–‹ã"</string> +</resources> diff --git a/play-services-base/res/values-ka-rGE/common_strings.xml b/play-services-base/res/values-ka-rGE/common_strings.xml new file mode 100644 index 0000000..9db9f63 --- /dev/null +++ b/play-services-base/res/values-ka-rGE/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play Services-ის შეცდáƒáƒ›áƒ"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ სáƒáƒáƒ˜áƒ áƒáƒ”ბრGoogle Play Services-ის ინსტáƒáƒšáƒáƒªáƒ˜áƒáƒ¡."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ სáƒáƒáƒ˜áƒ áƒáƒ”ბს Google Play Services-ის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒáƒ¡."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ სáƒáƒáƒ˜áƒ áƒáƒ”ბს Android Wear áƒáƒžáƒ˜áƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒáƒ¡."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ სáƒáƒáƒ˜áƒ áƒáƒ”ბს გáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ ებულ Google Play Services."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"მáƒáƒ›áƒ—ხáƒáƒ•áƒœáƒ˜: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play სერვისების მიღებáƒ"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ეს áƒáƒžáƒ˜ ვერგáƒáƒ”შვებრGoogle Play სერვისების გáƒáƒ ეშე, რáƒáƒª თქვენს ტელეფáƒáƒœáƒ–ე ვერიძებნებáƒ."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ეს áƒáƒžáƒ˜ ვერგáƒáƒ”შვებრGoogle Play სერვისების გáƒáƒ ეშე, რáƒáƒª თქვენს ტელეფáƒáƒœáƒ–ე ვერიძებნებáƒ."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play სერვისების მიღებáƒ"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play სერვისების გáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ ებáƒ"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"ეს áƒáƒžáƒ˜ áƒáƒ იმუშáƒáƒ•áƒ”ბს, თუ áƒáƒ გáƒáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ ებთ Google Play სერვისებს."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play სერვისების გáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ ებáƒ"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play სერვისების გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear-ის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"ეს áƒáƒžáƒ˜ ვერგáƒáƒ”შვებáƒ, თუ Google Play სერვისებს áƒáƒ გáƒáƒœáƒáƒáƒ®áƒšáƒ”ბთ."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"ეს áƒáƒžáƒ˜ ვერგáƒáƒ”შვებáƒ, თუ Android Wear áƒáƒžáƒ¡ áƒáƒ გáƒáƒœáƒáƒáƒ®áƒšáƒ”ბთ."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ქსელის შეცდáƒáƒ›áƒ"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play Services-თáƒáƒœ დáƒáƒ¡áƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებლáƒáƒ“ მáƒáƒœáƒáƒªáƒ”მთრგáƒáƒ“áƒáƒªáƒ”მრáƒáƒ£áƒªáƒ˜áƒšáƒ”ბელიáƒ."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"áƒáƒœáƒ’áƒáƒ იში áƒáƒ áƒáƒ¡áƒ¬áƒáƒ იáƒ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"მითითებული áƒáƒœáƒ’áƒáƒ იში áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე áƒáƒ áƒáƒ სებáƒáƒ‘ს. გთხáƒáƒ•áƒ—, áƒáƒ˜áƒ ჩიáƒáƒ— სხვრáƒáƒœáƒ’áƒáƒ იში."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play სერვისებთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებით უცნáƒáƒ‘ი შეფერხებრწáƒáƒ მáƒáƒ˜áƒ¨áƒ•áƒ."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play სერვისები"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play სერვისები, რáƒáƒª თქვენს ზáƒáƒ’იერთ áƒáƒžáƒ¡ áƒáƒ˜áƒ დებáƒ, თქვენს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე მხáƒáƒ დáƒáƒáƒ”რილი áƒáƒ áƒáƒ ის. გთხáƒáƒ•áƒ—, დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დეთ მწáƒáƒ მáƒáƒ”ბელს დáƒáƒ®áƒ›áƒáƒ ებისáƒáƒ—ვის."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"შესვლáƒ"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google-ით შესვლáƒ"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ტელეფáƒáƒœáƒ–ე გáƒáƒ®áƒ¡áƒœáƒ"</string> +</resources> diff --git a/play-services-base/res/values-kk-rKZ/common_strings.xml b/play-services-base/res/values-kk-rKZ/common_strings.xml new file mode 100644 index 0000000..ecc6b44 --- /dev/null +++ b/play-services-base/res/values-kk-rKZ/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play қызметтерінің қатеÑÑ–"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Қолданба Google Play қызметтерін орнатуды талап етеді."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Қолданба Google Play қызметтерін жаңартуды талап етеді."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Қолданба Android Wear қолданбаÑын жаңартуды қажет етеді."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Қолданба Google Play қызметтерін қоÑуды қажет етеді."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> арқылы Ñұралған"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play қызметтерін алу"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Телефоныңызда жоқ Google Play қызметтерінÑіз бұл қолданба Ñ–Ñке қоÑылмайды."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Планшетіңізде жоқ Google Play қызметтерінÑіз бұл қолданба Ñ–Ñке қоÑылмайды."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play қызметтерін алу"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play қызметтерін қоÑу"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Бұл қолданба Google Play қызметтерін қоÑқанша Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтемейді."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play қызметтерін қоÑу"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play қызметтерін жаңарту"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear қолданбаÑын жаңарту"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Бұл қолданба Google Play қызметтерін жаңартқанша Ñ–Ñке қоÑылмайды."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Бұл қолданба Android Wear қолданбаÑын жаңартқанша Ñ–Ñке қоÑылмайды."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Желі қатеÑÑ–"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play қызметтеріне қоÑылу үшін деректер байланыÑÑ‹ талап етіледі."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ЖарамÑыз тіркелгі"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Бұл құрылғыда көрÑетілген тіркелгі жоқ. БаÑқа тіркелгіні таңдаңыз."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play қызметтерімен белгіÑіз мәÑеле."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play қызметтері"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Кейбір қолданбаларыңыз үшін қажет Google Play қызметтеріне құрылғыңыз қолдау көрÑетпейді. Көмек алу үшін өндірушіге хабарлаÑыңыз."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Жаңарту"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Кіру"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google арқылы кіру"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Телефонда ашу"</string> +</resources> diff --git a/play-services-base/res/values-km-rKH/common_strings.xml b/play-services-base/res/values-km-rKH/common_strings.xml new file mode 100644 index 0000000..17fedd3 --- /dev/null +++ b/play-services-base/res/values-km-rKH/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"កំហុស​​សáŸážœáž¶áž€áž˜áŸ’ម​ Google កម្សាន្áž"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"កម្មវិធី​ទាមទារ​ឲ្យ​ដំឡើង​សáŸážœáž¶áž€áž˜áŸ’ម​ Google កម្សាន្ážáŸ”"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"កម្មវិធី​ទាមទារ​​ធ្វើ​បច្ចុប្បន្នភាព​សáŸážœáž¶áž€áž˜áŸ’ម ​Google កម្សាន្ážáŸ”"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"កម្មវិធី​ទាមទារ​បច្ចុប្បន្នភាព​ចំពោះ​កម្មវិធី Android Wear ។"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"កម្មវិធី​ទាមទារ​ឲ្យ​បើក​សáŸážœáž¶áž€áž˜áŸ’ម​ Google កម្សាន្ážáŸ”"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"បាន​ស្នើ​ដោយ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"ទទួល​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"កម្មវិធី​នáŸáŸ‡â€‹áž“ឹង​មិន​ដំណើរការ​​ទáŸâ€‹áž”ើ​គ្មាន​​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ážâ€‹ Google ដែល​ទូរសáŸáž–្ទ​របស់​​អ្នក​មិន​មាន។"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"​​កម្មវិធី​នáŸáŸ‡â€‹áž“ឹង​មិន​ដំណើរការ​​ទáŸâ€‹áž”ើ​គ្មាន​​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ážâ€‹ Google ដែល​​កុំព្យូទáŸážšâ€‹áž”ន្ទះ​របស់​អ្នក​មិន​មាន។"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"ទទួល​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"បើក​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"កម្ម​វិធី​នáŸáŸ‡â€‹áž“ឹង​មិន​ដំណើរការ​ទáŸâ€‹ លុះážáŸ’រាážáŸ‚​អ្នក​បើក​សáŸážœáž¶áž€áž˜áŸ’ម​​កម្សាន្ážâ€‹ Google ។"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"បើក​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"ធ្វើ​បច្ចុប្បន្នភាព​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"ធ្វើ​បច្ចុប្បន្នភាព Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"កម្មវិធី​នáŸáŸ‡â€‹áž“ឹង​មិន​ដំណើរការ​ទáŸâ€‹ លុះážáŸ’រាážáŸ‚​អ្នក​ធ្វើ​បច្ចុប្បន្នភាព​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle ។"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"កម្មវិធី​នáŸáŸ‡â€‹áž“ឹង​មិន​ដំណើរការ​ទ០លុះ​ážáŸ’រា​ážáŸ‚​អ្នក​ធ្វើ​បច្ចុប្បន្នភាព​​កម្មវិធី Android Wear ។"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"កំហុស​​បណ្ដាញ"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"បាន​ទាមទារ​ការ​ážáž—្ជាប់​ទិន្ននáŸáž™ ដើម្បី​ភ្ជាប់​សáŸážœáž¶áž€áž˜áŸ’ម​ឃ្លាំង​កម្មវិធី។"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"គណនី​មិន​ážáŸ’រឹមážáŸ’រូវ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"គណនី​ដែល​បាន​បញ្ជាក់​មិន​មាន​នៅ​លើ​ឧបករណáŸâ€‹áž“áŸáŸ‡â€‹áž‘áŸáŸ” សូម​ជ្រើស​គណនី​ផ្សáŸáž„​។"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"មិន​ស្គាល់​បញ្ហា​ជាមួយ​សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle ។"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ážâ€‹ Google"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"សáŸážœáž¶áž€áž˜áŸ’ម​កម្សាន្ហGoogle អាស្រáŸáž™â€‹áž›áž¾â€‹áž€áž˜áŸ’មវិធី​របស់​អ្នក មិន​ážáŸ’រូវ​បាន​គាំទ្រ​ដោយ​ឧបករណáŸâ€‹ážšáž”ស់​អ្នក។ សូម​ទាក់ទង​ក្រុមហ៊ុន​ផលិážâ€‹ážŸáž˜áŸ’រាប់​ជំនួយ។"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ធ្វើ​បច្ចុប្បន្នភាព"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ចូល"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"ចូល​ដោយ​ប្រើ​ Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"បើក​ážáž¶áž˜â€‹áž‘ូរសáŸáž–្ទ"</string> +</resources> diff --git a/play-services-base/res/values-kn-rIN/common_strings.xml b/play-services-base/res/values-kn-rIN/common_strings.xml new file mode 100644 index 0000000..e144daf --- /dev/null +++ b/play-services-base/res/values-kn-rIN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play ಸೇವೆಗಳ ದೋಷ"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œà²—ೆ Google Play ಸೇವೆಗಳೠಸà³à²¥à²¾à²ªà²¨à³†à²¯à²¾à²—ಿರಬೇಕಾಗà³à²¤à³à²¤à²¦à³†."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œà²—ೆ Google Play ಸೇವೆಗಳ ನವೀಕರಣದ ಅಗತà³à²¯à²µà²¿à²¦à³†."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android Wear ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ನವೀಕರಿಸಲೠಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ಅಗತà³à²¯à²µà²¿à²¦à³†."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œà²—ೆ Google Play ಸೇವೆಗಳೠಸಕà³à²°à²¿à²¯à²—ೊಂಡಿರಬೇಕಾಗà³à²¤à³à²¤à²¦à³†."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನಿಂದ ವಿನಂತಿಸಲಾಗಿದೆ"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play ಸೇವೆಗಳನà³à²¨à³ ಪಡೆಯಿರಿ"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ನಿಮà³à²® ಫೋನà³â€â€à²¨à²²à³à²²à²¿ ಕಾಣೆಯಾಗಿರà³à²µ ಈ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³, Google Play ಸೇವೆಗಳಿಲà³à²²à²¦à³† ಚಾಲನೆಯಾಗà³à²µà³à²¦à²¿à²²à³à²²."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ನಿಮà³à²® ಟà³à²¯à²¾à²¬à³à²²à³†à²Ÿà³â€à²¨à²²à³à²²à²¿ ಕಾಣೆಯಾಗಿರà³à²µ ಈ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³, Google Play ಸೇವೆಗಳಿಲà³à²²à²¦à³† ಚಾಲನೆಯಾಗà³à²µà³à²¦à²¿à²²à³à²²."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play ಸೇವೆಗಳನà³à²¨à³ ಪಡೆಯಿರಿ"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play ಸೇವೆಗಳನà³à²¨à³ ಸಕà³à²°à²¿à²¯à²—ೊಳಿಸಿ"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Google Play ಸೇವೆಗಳನà³à²¨à³ ನೀವೠಸಕà³à²°à²¿à²¯à²—ೊಳಿಸದ ಹೊರತೠಈ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ಕಾರà³à²¯à²¨à²¿à²°à³à²µà²¹à²¿à²¸à³à²µà³à²¦à²¿à²²à³à²²."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play ಸೇವೆಗಳನà³à²¨à³ ಸಕà³à²°à²¿à²¯à²—ೊಳಿಸಿ"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play ಸೇವೆಗಳನà³à²¨à³ ನವೀಕರಿಸಿ"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear ನವೀಕರಿಸಿ"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"ನೀವೠGoogle Play ಸೇವೆಗಳನà³à²¨à³ ನವೀಕರಿಸದ ಹೊರತೠಈ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ಚಾಲನೆಯಾಗà³à²µà³à²¦à²¿à²²à³à²²."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"ನೀವà³Â Android Wear ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ನವೀಕರಿಸದ ಹೊರತೠಈ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ರನೠಆಗà³à²µà³à²¦à²¿à²²à³à²²."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ನೆಟà³â€à²µà²°à³à²•à³ ದೋಷ"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play ಸೇವೆಗಳಿಗೆ ಸಂಪರà³à²• ಹೊಂದಲೠಡೇಟಾ ಸಂಪರà³à²•à²¦ ಅಗತà³à²¯à²µà²¿à²¦à³†."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ಅಮಾನà³à²¯à²µà²¾à²¦ ಖಾತೆ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ಈ ಸಾಧನದಲà³à²²à²¿ ನಿರà³à²¦à²¿à²·à³à²Ÿà²ªà²¡à²¿à²¸à²²à²¾à²¦ ಖಾತೆಯೠಅಸà³à²¤à²¿à²¤à³à²µà²¦à²²à³à²²à²¿à²²à³à²². ದಯವಿಟà³à²Ÿà³ ಬೇರೆಯ ಖಾತೆಯನà³à²¨à³ ಆಯà³à²•à³†à²®à²¾à²¡à²¿."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play ಸೇವೆಗಳಿಗೆ ಅಜà³à²žà²¾à²¤ ಸಮಸà³à²¯à³†."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play ಸೇವೆಗಳà³"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"ನಿಮà³à²® ಕೆಲವೠಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œà²—ಳೠಅವಂಬಿಸಿರà³à²µà²‚ತಹ Google Play ಸೇವೆಗಳನà³à²¨à³ ನಿಮà³à²® ಸಾಧನವೠಬೆಂಬಲಿಸà³à²µà³à²¦à²¿à²²à³à²². ದಯವಿಟà³à²Ÿà³ ನೆರವಿಗಾಗಿ ಉತà³à²ªà²¾à²¦à²•à²°à²¨à³à²¨à³ ಸಂಪರà³à²•à²¿à²¸à²¿."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ನವೀಕರಿಸà³"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ಸೈನೠಇನೠಮಾಡà³"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google ಜೊತೆ ಸೈನೠಇನೠಮಾಡಿ"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ಫೋನà³â€Œà²¨à²²à³à²²à²¿ ತೆರೆಯಿರಿ"</string> +</resources> diff --git a/play-services-base/res/values-ko/common_strings.xml b/play-services-base/res/values-ko/common_strings.xml new file mode 100644 index 0000000..9271b80 --- /dev/null +++ b/play-services-base/res/values-ko/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play 서비스 오류"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Google Play 서비스를 설치해야 하는 ì• í”Œë¦¬ì¼€ì´ì…˜ìž…니다."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Google Play 서비스를 ì—…ë°ì´íŠ¸í•´ì•¼ 하는 ì• í”Œë¦¬ì¼€ì´ì…˜ìž…니다."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android Wear ì•±ì— ëŒ€í•œ ì—…ë°ì´íŠ¸ê°€ 필요한 ì• í”Œë¦¬ì¼€ì´ì…˜ì´ 있습니다."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Google Play 서비스를 사용 ì„¤ì •í•´ì•¼ 하는 ì• í”Œë¦¬ì¼€ì´ì…˜ìž…니다."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g>ì—ì„œ ìš”ì²"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play 서비스 설치"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"íœ´ëŒ€ì „í™”ì— Google Play 서비스가 설치ë˜ì–´ 있어야 ì´ ì•±ì´ ì‹¤í–‰ë©ë‹ˆë‹¤."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"íƒœë¸”ë¦¿ì— Google Play 서비스가 설치ë˜ì–´ 있어야 ì´ ì•±ì´ ì‹¤í–‰ë©ë‹ˆë‹¤."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play 서비스 설치"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play 서비스 사용"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Google Play 서비스를 사용하ë„ë¡ ì„¤ì •í•´ì•¼ ì´ ì•±ì´ ìž‘ë™í•©ë‹ˆë‹¤."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play 서비스 사용"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play 서비스 ì—…ë°ì´íŠ¸"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear ì—…ë°ì´íŠ¸"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Google Play 서비스를 ì—…ë°ì´íŠ¸í•´ì•¼ë§Œ ì´ ì•±ì´ ì‹¤í–‰ë©ë‹ˆë‹¤."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android Wear ì•±ì„ ì—…ë°ì´íŠ¸í•´ì•¼ë§Œ ì´ ì•±ì´ ì‹¤í–‰ë©ë‹ˆë‹¤."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ë„¤íŠ¸ì›Œí¬ ì˜¤ë¥˜"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play ì„œë¹„ìŠ¤ì— ì—°ê²°í•˜ë ¤ë©´ ë°ì´í„° ì—°ê²°ì´ í•„ìš”í•©ë‹ˆë‹¤."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"올바르지 ì•Šì€ ê³„ì •"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ì§€ì •í•œ ê³„ì •ì´ ì´ ê¸°ê¸°ì— ì¡´ìž¬í•˜ì§€ 않습니다. 다른 ê³„ì •ì„ ì„ íƒí•˜ì„¸ìš”."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play ì„œë¹„ìŠ¤ì— ì•Œ 수 없는 ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play 서비스"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"ì¼ë¶€ ì‚¬ìš©ìž ì• í”Œë¦¬ì¼€ì´ì…˜ì— 필요한 Google Play 서비스가 ì‚¬ìš©ìž ê¸°ê¸°ì—ì„œ 지ì›ë˜ì§€ 않습니다. 기기 ì œì¡°ì—…ì²´ì— ë¬¸ì˜í•˜ì‹œê¸° ë°”ëžë‹ˆë‹¤."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ì—…ë°ì´íŠ¸"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"로그ì¸"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google ê³„ì •ìœ¼ë¡œ 로그ì¸"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"íœ´ëŒ€ì „í™”ì—ì„œ 열기"</string> +</resources> diff --git a/play-services-base/res/values-ky-rKG/common_strings.xml b/play-services-base/res/values-ky-rKG/common_strings.xml new file mode 100644 index 0000000..e92e31f --- /dev/null +++ b/play-services-base/res/values-ky-rKG/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play кызматтарынын катаÑÑ‹"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Колдонмону иштетүү үчүн, Google Play кызматтарын орнотуу керек."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Колдонмону иштетүү үчүн, Google Play Кызматтарын жаңыртуу керек."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Колдонмону Android Тагынма колдонмоÑуна жаңыртуу керек."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Колдонмону иштетүү үчүн, Google Play Кызматтарын иштетүү керек."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> Ñурап жатат"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play кызматтарын алуу"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Бул колдонмо Google Play кызматтарыÑыз иштебейт, алар Ñиздин телефонуңузда жок."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Бул колдонмо Google Play кызматтарыÑыз иштебейт, алар Ñиздин планшетиңизде жок."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play кызматтарын алуу"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play кызматтарын иштетүү"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Бул колдонмо Google Play кызматтары иштетилмейинче иштебейт."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play кызматтарын иштетүү"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play кызматтарын жаңыртуу"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Тагынманы жаңыртуу"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Бул колдонмо Google Play кызматтары жаңыртылмайынча иштебейт."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android Тагынма колдонмоÑу жаңыртылмайынча бул колдонмо иштебейт."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Тармак катаÑÑ‹"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play Кызматтарына туташуу үчүн, дайындарды өткөрүүчү туташуу талап кылынат."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Каттоо ÑÑеби жаракÑыз"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"КөрÑөтүлгөн каттоо ÑÑеби бул түзмөктө жок. Башка каттоо ÑÑебин тандаңыз."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play кызматтарында келип чыккан белгиÑиз көйгөй."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play кызматтары"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Ðйрым колдонмолоруңузга байланышкан Google Play кызматтары түзмөгүңүздө колдоого алынбайт. Жардам алуу үчүн өндүрүүчүгө кайрылыңыз."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Жаңыртуу"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Кирүү"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google менен кирүү"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Телефондо ачык"</string> +</resources> diff --git a/play-services-base/res/values-lo-rLA/common_strings.xml b/play-services-base/res/values-lo-rLA/common_strings.xml new file mode 100644 index 0000000..ebdd89d --- /dev/null +++ b/play-services-base/res/values-lo-rLA/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play Services ​ເàºàºµàº”​ຄວາມ​ຜິດ​ພາດ"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"​à»àºàº±àºšâ€‹àºžâ€‹àº¥àº´â€‹à»€àº„​ຊັນ​ຕ້àºàº‡â€‹àºàº²àº™â€‹à»ƒàº«à»‰â€‹àº•àº´àº”​ຕັ້ງ​ບà»â€‹àº¥àº´â€‹àºàº²àº™ Google Play àºà»ˆàºàº™."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"​à»àºàº±àºšâ€‹àºžâ€‹àº¥àº´â€‹à»€àº„​ຊັນ​ຕ້àºàº‡â€‹àºàº²àº™â€‹à»ƒàº«à»‰â€‹àºàº±àºšâ€‹à»€àº”ດບà»â€‹àº¥àº´â€‹àºàº²àº™ Google Play àºà»ˆàºàº™."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"à»àºàº±àºšàº°â€‹àº¥àº´â€‹à»€àº„​ຊັນ​ຕ້àºàº‡â€‹àºàº²àº™â€‹à»ƒàº«à»‰â€‹àºàº±àºšâ€‹à»€àº”ດ​à»àºàº±àºšàº¯ Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"à»àºàº±àºšàºžàº¥àº´à»€àº„ຊັນຕ້àºàº‡â€‹àºàº²àº™àº™àº³à»ƒàºŠà»‰ Google Play Services."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"ຮ້àºàº‡àº‚à»à»‚ດຠ<xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"ຕິດຕັ້ງບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"à»àºàº±àºšàº¯àº™àºµà»‰àºˆàº°àºšà»à»ˆàºªàº²àº¡àº²àº”ເຮັດວຽàºà»„ດ້ໂດàºàº—ີ່ບà»à»ˆàº¡àºµàºšà»àº¥àº´àºàº²àº™ Google Play ເຊິ່ງຂາດຫາàºà»„ປໃນໂທລະສັບຂàºàº‡àº—່ານ."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"à»àºàº±àºšàº¯àº™àºµà»‰àºˆàº°àºšà»à»ˆàºªàº²àº¡àº²àº”ເຮັດວຽàºà»„ດ້ໂດàºàº—ີ່ບà»à»ˆàº¡àºµàºšà»àº¥àº´àºàº²àº™ Google Play ເຊິ່ງຂາດຫາàºà»„ປໃນà»àº—ັບເລັດຂàºàº‡àº—່ານ."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"ຕິດຕັ້ງບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"ເປີດໃຊ້ບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"à»àºàº±àºšàº¯àº™àºµà»‰àºˆàº°àºšà»à»ˆàºªàº²àº¡àº²àº”ເຮັດວຽàºà»„ດ້ຈົນàºàº§à»ˆàº²àº—່ານຈະເປີດໃຊ້ບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"ເປີດໃຊ້ບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"àºàº±àºšà»€àº”ດບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"​àºàº±àºšâ€‹à»€àº”ດ Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"à»àºàº±àºšàº¯àº™àºµà»‰àºˆàº°àºšà»à»ˆàºªàº²àº¡àº²àº”ເຮັດວຽàºà»„ດ້ຈົນàºàº§à»ˆàº²àº—່ານຈະàºàº±àºšà»€àº”ດບà»àº¥àº´àºàº²àº™ Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"à»àºàº±àºšàº¯â€‹àº™àºµà»‰â€‹àºˆàº°â€‹àºšà»à»ˆâ€‹àºªàº²â€‹àº¡àº²àº”​ໃຊ້​ໄດ້​ຈົນ​àºàº§à»ˆàº²â€‹àº—່ານ​ຈະ​àºàº±àºšâ€‹à»€àº”ດ​à»àºàº±àºšàº¯ Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ເຄືàºàº‚່າàºàºœàº´àº”ພາດ"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ຕ້àºàº‡à»ƒàºŠà»‰àºàº²àº™à»€àºŠàº·à»ˆàºàº¡àº•à»à»ˆàºàº´àº™à»€àº•àºµà»€àº™àº±àº”ເພື່àºà»ƒàºŠà»‰ Google Play Services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ບັນຊີບà»à»ˆàº–ືàºàº•à»‰àºàº‡"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ບັນຊີທີ່ເລືàºàºàºšà»à»ˆàº¡àºµà»ƒàº™àºàº¸àº›àº°àºàºàº™àº™àºµà»‰. àºàº°àº¥àº¸àº™àº²à»€àº¥àº·àºàºàºšàº±àº™àºŠàºµàºàº·à»ˆàº™."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"ມີປັນຫາທີ່ບà»à»ˆàº„າດຄິດໃນບà»àº¥àº´àºàº²àº™ Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"ບà»àº¥àº´àºàº²àº™ Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"ບà»àº¥àº´àºàº²àº™ Google Play ທີ່ບາງà»àºàº±àºšàºžàº¥àº´à»€àº„ຊັນຂàºàº‡àº—່ານຕ້àºàº‡àºàº²à»„ສນັ້ນ ບà»à»ˆàº–ືàºàº®àºàº‡àº®àº±àºšà»ƒàº™àºàº¸àº›àº°àºàºàº™àº‚àºàº‡àº—່ານ. àºàº°àº¥àº¸àº™àº²àº•àº´àº”ຕà»à»ˆàºœàº¹à»‰àºœàº°àº¥àº´àº”ສຳລັບàºàº²àº™à»àº™àº°àº™àº³."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"àºàº±àºšà»€àº”ດ"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ເຂົ້າສູ່ລະບົບ"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"ເຂົ້າສູ່ລະບົບດ້ວຠGoogle"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"​ເປີດ​ໃນ​ໂທ​ລະ​ສັບ"</string> +</resources> diff --git a/play-services-base/res/values-lt/common_strings.xml b/play-services-base/res/values-lt/common_strings.xml new file mode 100644 index 0000000..235dad8 --- /dev/null +++ b/play-services-base/res/values-lt/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"„Google Play“ paslaugų klaida"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Norint naudoti programÄ… bÅ«tina įdiegti „Google Play“ paslaugas."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Norint naudoti programÄ… bÅ«tina atnaujinti „Google Play“ paslaugas."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Programai reikalingas „Android Wear“ programos naujinys."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Norint naudoti programÄ… bÅ«tina įgalinti „Google Play“ paslaugas."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"UžklausÄ… pateikÄ— „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Gauti „Google Play“ paslaugų"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Å i programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos telefone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Å i programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos planÅ¡etiniame kompiuteryje."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Gauti „Google Play“ paslaugų"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ä®galinti „Google Play“ paslaugas"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Å i programa neveiks, jei neįgalinsite „Google Play“ paslaugų."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ä®gal. „Google Play“ paslaugas"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atnaujinti „Google Play“ paslaugas"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Atnaujinkite „Android Wear“"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Å i programa neveiks, jei neatnaujinsite „Google Play“ paslaugų."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Å i programa veiks tik atnaujinus „Android Wear“ programÄ…."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Tinklo klaida"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Norint prisijungti prie „Google Play“ paslaugų reikia duomenų ryÅ¡io."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Netinkama paskyra"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Nurodytos paskyros Å¡iame įrenginyje nÄ—ra. Pasirinkite kitÄ… paskyrÄ…."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nežinoma „Google Play“ paslaugų problema."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"„Google Play“ paslaugos"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"JÅ«sų įrenginys nepalaiko „Google Play“ paslaugų, kuriomis remiasi kai kurios programos. Jei reikia pagalbos, susisiekite su gamintoju."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atnaujinti"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Prisij."</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prisij. naud. „Google“"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Atidaryti telefonu"</string> +</resources> diff --git a/play-services-base/res/values-lv/common_strings.xml b/play-services-base/res/values-lv/common_strings.xml new file mode 100644 index 0000000..93dd0e3 --- /dev/null +++ b/play-services-base/res/values-lv/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play pakalpojumu kļūda"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Lai lietojumprogramma darbotos, jÄinstalÄ“ Google Play pakalpojumi."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Lai lietojumprogramma darbotos, jÄatjaunina Google Play pakalpojumi."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Lai nodroÅ¡inÄtu kÄdas lietojumprogrammas darbÄ«bu, jÄatjaunina lietotne Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Lai lietojumprogramma darbotos, jÄiespÄ“jo Google Play pakalpojumi."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"PieprasÄ«jums no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play pakalpojumu iegÅ«Å¡ana"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Lai Å¡Ä« lietotne darbotos, tÄlrunÄ« ir jÄinstalÄ“ Google Play pakalpojumi."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Lai Å¡Ä« lietotne darbotos, planÅ¡etdatorÄ ir jÄinstalÄ“ Google Play pakalpojumi."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"IegÅ«t Google Play pakalpojumus"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play pakalpojumu iespÄ“joÅ¡ana"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Lai Å¡Ä« lietotne darbotos, iespÄ“jojiet Google Play pakalpojumus."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"IespÄ“jot Google Play pakalpojumus"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play pakalpojumu atjauninÄÅ¡ana"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear atjauninÄÅ¡ana"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Lai Å¡Ä« lietotne darbotos, atjauniniet Google Play pakalpojumus."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Å Ä« lietotne nedarbosies, ja neatjauninÄsiet lietotni Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"TÄ«kla kļūda"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Lai izveidotu savienojumu ar Google Play pakalpojumiem, ir nepiecieÅ¡ams datu savienojums."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"NederÄ«gs konts"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"NorÄdÄ«tais konts Å¡ajÄ ierÄ«cÄ“ nepastÄv. LÅ«dzu, izvÄ“lieties citu kontu."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"NezinÄma problÄ“ma ar Google Play pakalpojumiem."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play pakalpojumi"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"JÅ«su ierÄ«ce neatbalsta Google Play pakalpojumus, kuri nepiecieÅ¡ami dažu jÅ«su lietojumprogrammu darbÄ«bai. LÅ«dzu, sazinieties ar ražotÄju, lai saņemtu palÄ«dzÄ«bu."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"AtjauninÄt"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Pierakst."</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"PierakstÄ«ties Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"AtvÄ“rt tÄlrunÄ«"</string> +</resources> diff --git a/play-services-base/res/values-mk-rMK/common_strings.xml b/play-services-base/res/values-mk-rMK/common_strings.xml new file mode 100644 index 0000000..c675f41 --- /dev/null +++ b/play-services-base/res/values-mk-rMK/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Грешка на уÑлугите на Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Ðпликацијата бара да Ñе инÑталираат уÑлугите на Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Ðпликацијата бара да Ñе ажурираат уÑлугите на Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Една апликација бара ажурирање на апликацијата Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ðпликацијата бара да Ñе овозможат уÑлугите на Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Побарал <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Преземи ги уÑлугите на Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ðпликацијата нема да работи без уÑлугите на Google Play, кои недоÑтаÑуваат од вашиот телефон."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ðпликацијата нема да работи без уÑлугите на Google Play, кои недоÑтаÑуваат од вашиот таблет."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Преземи ги уÑлугите на Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Овозможи ги уÑлугите на Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ðпликацијата нема да работи ако не ги овозможите уÑлугите на Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Овозможи ги уÑлугите на Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ðжурирај ги уÑлугите на Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Ðжурирај Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ðпликацијата нема да работи ако не ги ажурирате уÑлугите на Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ðпликацијата нема да работи ако не ја ажурирате апликацијата Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Мрежна грешка"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Потребно е поврзување податоци за да Ñе поврзете Ñо уÑлугите на Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ðеважечка Ñметка"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Ðаведената Ñметка не поÑтои на овој уред. Изберете друга Ñметка."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ðепознат проблем Ñо уÑлугите на Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"УÑлуги на Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Уредот не ги поддржува уÑлугите на Google Play на кои Ñе потпираат некои од вашите апликации. Контактирајте Ñо производителот за помош."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ðжурирај"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Ðајави Ñе"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Ðајави Ñе Ñо Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Отвори на телефонот"</string> +</resources> diff --git a/play-services-base/res/values-ml-rIN/common_strings.xml b/play-services-base/res/values-ml-rIN/common_strings.xml new file mode 100644 index 0000000..d540d05 --- /dev/null +++ b/play-services-base/res/values-ml-rIN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play സേവനങàµà´™à´³à´¿à´²àµ† പിശകàµ"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"ഒരൠഅപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµ Google Play സേവനങàµà´™àµ¾ ഇൻസàµâ€Œà´±àµà´±à´¾à´³àµà´šàµ†à´¯àµà´¯àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"ഒരൠഅപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµ Google Play സേവനങàµà´™àµ¾ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¯àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"ഒരൠഅപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµ Android Wear à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨à´¿à´²àµ‡à´•àµà´•àµ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ആവശàµà´¯à´®à´¾à´£àµ."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"ഒരൠഅപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµ Google Play സേവനങàµà´™àµ¾ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> à´…à´àµà´¯àµ¼à´¤àµà´¥à´¿à´šàµà´šà´¤àµ"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play സേവനങàµà´™àµ¾ നേടàµà´•"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"നിങàµà´™à´³àµà´Ÿàµ† ഫോണിൽ നിനàµà´¨àµà´‚ നഷàµâ€Œà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´Ÿ Google Play സേവനങàµà´™à´³à´¿à´²àµà´²à´¾à´¤àµ† à´ˆ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´¯àµà´•àµà´•à´¿à´²àµà´²."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"നിങàµà´™à´³àµà´Ÿàµ† ടാബàµâ€Œâ€Œà´²àµ†à´±àµà´±à´¿àµ½ നിനàµà´¨àµà´‚ നഷàµâ€Œà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´Ÿ Google Play സേവനങàµà´™à´³à´¿à´²àµà´²à´¾à´¤àµ† à´ˆ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´¯àµà´•àµà´•à´¿à´²àµà´²."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play സേവനങàµà´™àµ¾ നേടàµà´•"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play സേവനങàµà´™àµ¾ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•àµà´•"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"നിങàµà´™àµ¾ Google Play സേവനങàµà´™àµ¾ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•à´¿à´¯à´¿à´²àµà´²àµ†à´™àµà´•à´¿àµ½ à´ˆ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´¯àµà´•àµà´•à´¿à´²àµà´²."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play സേവനങàµà´™àµ¾ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•àµà´•"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play സേവനങàµà´™àµ¾ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´•"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´•"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"നിങàµà´™àµ¾ Google Play സേവനങàµà´™àµ¾ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµâ€Œà´¤à´¿à´²àµà´²àµ†à´™àµà´•à´¿àµ½ à´ˆ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•à´¿à´²àµà´²."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"നിങàµà´™àµ¾ Android Wear à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¯à´¾à´¤àµà´¤à´¿à´Ÿà´¤àµà´¤àµ‹à´³à´‚ à´ˆ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•à´¿à´²àµà´²."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ പിശകàµ"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play സേവനങàµà´™à´³à´¿à´²àµ‡à´¯àµà´•àµà´•àµ കണകàµà´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ ഒരൠഡാറàµà´± കണകàµà´·àµ» ആവശàµà´¯à´®à´¾à´£àµ."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"à´…à´•àµà´•àµ—à´£àµà´Ÿàµ അസാധàµà´µà´¾à´£àµ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"à´µàµà´¯à´•àµà´¤à´®à´¾à´•àµà´•à´¿à´¯ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ à´ˆ ഉപകരണതàµà´¤à´¿àµ½ നിലവിലിലàµà´². മറàµà´±àµŠà´°àµ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play സേവനങàµà´™à´³à´¿à´²àµ† à´…à´œàµà´žà´¾à´¤ à´ªàµà´°à´¶àµâ€Œà´¨à´‚."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play സേവനങàµà´™àµ¾"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"നിങàµà´™à´³àµà´Ÿàµ† à´šà´¿à´² à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾ ആശàµà´°à´¯à´¿à´•àµà´•àµà´¨àµà´¨ Google Play സേവനങàµà´™à´³àµ† നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണം പിനàµà´¤àµà´£à´¯àµà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´². സഹായതàµà´¤à´¿à´¨à´¾à´¯à´¿ നിർമàµà´®à´¾à´¤à´¾à´µà´¿à´¨àµ† ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´•"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"സൈൻ ഇൻ ചെയàµà´¯àµà´•"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google ഉപയോഗിചàµà´šàµ സൈൻ ഇൻ ചെയàµà´¯àµà´•"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ഫോണിൽ à´¤àµà´±à´•àµà´•àµà´•"</string> +</resources> diff --git a/play-services-base/res/values-mn-rMN/common_strings.xml b/play-services-base/res/values-mn-rMN/common_strings.xml new file mode 100644 index 0000000..01556f9 --- /dev/null +++ b/play-services-base/res/values-mn-rMN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Ðаадаан үйлчилгÑÑний алдаа"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Ðппликешн Google Ðаадаан ҮйлчилгÑÑг Ñуулгахыг шаардана."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Ðппликешн Google Ðаадаан ҮйлчилгÑÑг шинÑчлÑхийг шаардана."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ðппликешнийг Ðндройд ЗүүÑгÑл апп болгон шинÑчлÑÑ… шаардлагатай."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ðппликешн Google Ðаадаан ҮйлчилгÑÑг идÑвхжүүлÑÑн байхыг шаардана."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> Ñ…Ò¯ÑÑлт гаргаÑан"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play үйлчилгÑÑ Ð°Ð²Ð°Ñ…"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Таны утÑанд байхгүй байгаа Google Play үйлчилгÑÑг идÑвхжүүлж байж ÑÐ½Ñ Ð°Ð¿Ð¿-г ажиллуулах боломжтой."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Таны таблетÑд байхгүй Google Play үйлчилгÑÑг идÑвхжүүлж байж ÑÐ½Ñ Ð°Ð¿Ð¿-г ажиллуулах боломжтой."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play үйлчилгÑÑ Ð°Ð²Ð°Ñ…"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play үйлчилгÑÑг идÑвхжүүлÑÑ…"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Та Google Play үйлчилгÑÑг идÑвхжүүлж байж ÑÐ½Ñ Ð°Ð¿Ð¿-г ажиллуулах боломжтой."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play үйлчилгÑÑг идÑвхжүүлÑÑ…"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play үйлчилгÑÑг шинÑчлÑÑ…"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Ðндройд ЗүүÑгÑлийг шинÑчлÑÑ…"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Та Google Play үйлчилгÑÑг шинÑчлÑхгүй бол ÑÐ½Ñ Ð°Ð¿Ð¿ ажиллах боломжгүй."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ðндройд ЗүүÑгÑл апп-г шинÑчлÑÑ…ÑÑÑ Ð½Ð°Ð°Ñˆ ÑÐ½Ñ Ð°Ð¿Ð¿ ажиллахгүй."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"СүлжÑÑний алдаа"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play үйлчилгÑÑнд холбогдохын тулд дата холболт шаардлагатай."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Буруу акаунт"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ЗааÑан акаунт ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑÑ€ байхгүй байна. Ó¨Ó©Ñ€ акаунт Ñонгоно уу."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play үйлчилгÑÑÑ‚Ñй холбоотой тодорхойгүй алдаа."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play үйлчилгÑÑ"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Таны зарим аппликешнүүдийн хамаардаг Google Play үйлчилгÑÑ Ñ‚Ð°Ð½Ñ‹ төхөөрөмжид дÑмжигдÑхгүй байна. ТуÑламж авахын тулд үйлдвÑрлÑгчтÑй холбоо барина уу."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ШинÑчлÑÑ…"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ÐÑвтрÑÑ…"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google-Ñ€ нÑвтрÑÑ…:"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"УтÑан дÑÑÑ€ нÑÑÑ…"</string> +</resources> diff --git a/play-services-base/res/values-mr-rIN/common_strings.xml b/play-services-base/res/values-mr-rIN/common_strings.xml new file mode 100644 index 0000000..d1a408e --- /dev/null +++ b/play-services-base/res/values-mr-rIN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play सेवा तà¥à¤°à¥à¤Ÿà¥€"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ासाठी Google Play सेवांची सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ आवशà¥à¤¯à¤• आहे."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ासाठी Google Play सेवांचे अदà¥à¤¯à¤¤à¤¨ आवशà¥à¤¯à¤• आहे."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ास Android Wear अॅप अदà¥à¤¯à¤¤à¤¨à¤¿à¤¤ करणà¥à¤¯à¤¾à¤šà¥€ आवशà¥à¤¯à¤•à¤¤à¤¾ आहे."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ासाठी Google Play सेवा सकà¥à¤·à¤® केलेलà¥à¤¯à¤¾ असणे आवशà¥à¤¯à¤• आहे."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> दà¥à¤µà¤¾à¤°à¥‡ विनंती केली"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play सेवा मिळवा"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"हा अॅप Google Play सेवांशिवाय चालणार नाही, जà¥à¤¯à¤¾ आपलà¥à¤¯à¤¾ फोनवरून गहाळ à¤à¤¾à¤²à¥à¤¯à¤¾ आहेत."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"हा अॅप Google Play सेवांशिवाय चालणार नाही, जà¥à¤¯à¤¾ आपलà¥à¤¯à¤¾ टॅबà¥à¤²à¥‡à¤Ÿà¤µà¤°à¥‚न गहाळ आहेत."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play सेवा मिळवा"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play सेवा सकà¥à¤·à¤® करा"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"आपण Google Play सेवा सकà¥à¤·à¤® केलà¥à¤¯à¤¾à¤¶à¤¿à¤µà¤¾à¤¯ हा अॅप कारà¥à¤¯ करणार नाही."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play सेवा सकà¥à¤·à¤® करा"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play सेवा अदà¥à¤¯à¤¤à¤¨à¤¿à¤¤ करा"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear अदà¥à¤¯à¤¤à¤¨à¤¿à¤¤ करा"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"आपण Google Play सेवा अदà¥à¤¯à¤¤à¤¨à¤¿à¤¤ केलà¥à¤¯à¤¾à¤¶à¤¿à¤µà¤¾à¤¯ हा अॅप चालणार नाही."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"आपण Android Wear अॅप अदà¥à¤¯à¤¤à¤¨à¤¿à¤¤ केलà¥à¤¯à¤¾à¤¶à¤¿à¤µà¤¾à¤¯ हा अॅप कारà¥à¤¯ करणार नाही."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"नेटवरà¥à¤• तà¥à¤°à¥à¤Ÿà¥€"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play सेवांशी कनेकà¥à¤Ÿ होणà¥à¤¯à¤¾à¤¸à¤¾à¤ ी डेटा कनेकà¥à¤¶à¤¨ आवशà¥à¤¯à¤• आहे."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"अवैध खाते"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ केलेले खाते या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° असà¥à¤¤à¤¿à¤¤à¥à¤µà¤¾à¤¤ नाही. कृपया à¤à¤• à¤à¤¿à¤¨à¥à¤¨ खाते निवडा."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play सेवांसह अजà¥à¤žà¤¾à¤¤ समसà¥à¤¯à¤¾."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play सेवा"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"आपले काही अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— जà¥à¤¯à¤¾à¤µà¤° अवलंबून आहेत अशी, Google Play सेवा, आपलà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤¦à¥à¤µà¤¾à¤°à¥‡ समरà¥à¤¥à¤¿à¤¤ नाही. कृपया सहायà¥à¤¯à¤¾à¤¸à¤¾à¤ ी निरà¥à¤®à¤¾à¤¤à¥à¤¯à¤¾à¤¶à¥€ संपरà¥à¤• साधा."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"अदà¥à¤¯à¤¤à¤¨à¤¿à¤¤ करा"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"साइन इन करा"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google सह साइन इन करा"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"फोनवर उघडा"</string> +</resources> diff --git a/play-services-base/res/values-ms-rMY/common_strings.xml b/play-services-base/res/values-ms-rMY/common_strings.xml new file mode 100644 index 0000000..e25985b --- /dev/null +++ b/play-services-base/res/values-ms-rMY/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Ralat perkhidmatan Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Perkhidmatan Google Play perlu dipasang utk menggunakan aplikasi."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Perkhidmatan Google Play perlu dikemas kini utk menggunakan aplikasi."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Apl memerlukan kemas kini kepada apl Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Perkhidmatan Google Play perlu didayakan untuk menggunakan aplikasi."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Diminta oleh <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Dapatkan perkhidmatan Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada telefon anda."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada tablet anda."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Dapatkan perkhidmatan Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Dayakan perkhidmatan Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Apl ini tidak akan berfungsi kecuali anda mendayakan perkhidmatan Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Dayakan perkhidmatan Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Kemas kini perkhidmatan Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Kemas kini Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Apl ini tidak akan berfungsi kecuali anda mengemas kini perkhidmatan Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Apl ini tidak akan berfungsi melainkan anda mengemas kini apl Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Ralat Rangkaian"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Sambungan data diperlukan untuk menyambung ke perkhidmatan Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Akaun Tidak Sah"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Akaun yang dinyatakan tidak wujud pada peranti ini. Sila pilih akaun yang lain."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Isu tidak diketahui dengan perkhidmatan Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Perkhidmatan Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Peranti anda tidak menyokong perkhidmatan Google Play, sedangkan sesetengah aplikasi anda memerlukannya. Sila hubungi pengilang untuk bantuan."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Kemas kini"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Log masuk"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Log masuk dengan Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Buka pada telefon"</string> +</resources> diff --git a/play-services-base/res/values-my-rMM/common_strings.xml b/play-services-base/res/values-my-rMM/common_strings.xml new file mode 100644 index 0000000..1633851 --- /dev/null +++ b/play-services-base/res/values-my-rMM/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google ပလေး á€á€”်ဆောင်မှုများ အမှား"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"အပလီကေးရှင်း á€á€…်á€á€¯ အá€á€½á€€á€º Google ပလေး á€á€”်ဆောင်မှုများကá€á€¯ á€á€•á€ºá€†á€„်ပေးရန် လá€á€¯á€žá€Šá€ºá‹"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"အပလီကေးရှင်း á€á€…်á€á€¯ အá€á€½á€€á€º Google ပလေး á€á€”်ဆောင်မှုကá€á€¯ မွမ်းမံပေးရန် လá€á€¯á€žá€Šá€ºá‹"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"အပလီကေးရှင်း á€á€…်á€á€¯á€€ အန်ဒရွá€á€¯á€€á€º ဆောင်စရာ appကá€á€¯ မွမ်းမံပေးရန်ကá€á€¯ á€á€±á€¬á€„်းဆá€á€¯á€”ေသည်á‹"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"အပလီကေးှရင်း á€á€…်á€á€¯ အá€á€½á€€á€º Google ပလေး á€á€”်ဆောင်မှုကá€á€¯ ဖွင့်ပေးရန် လá€á€¯á€¡á€•á€ºá€žá€Šá€ºá‹"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> က á€á€±á€¬á€„်းဆá€á€¯á€á€²á€·á€žá€Šá€º"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google ပလေး á€á€”်ဆောင်မှုများကá€á€¯ ရယူပါá‹"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ဤappသည် သင့်ဖုန်းထဲá€á€½á€„် မရှá€á€žá€Šá€·á€º Google ပလေး á€á€”်ဆောင်မှုများ မရှá€á€œá€»á€¾á€„် အလုပ်လုပ်မည် မဟုá€á€ºá€•á€«á‹"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"သင် á€á€€á€ºá€˜á€œá€€á€º ထဲá€á€½á€„် မရှá€á€žá€Šá€·á€º Google ပလေး á€á€”်ဆောင်မှုများ မရှá€á€œá€»á€¾á€„် အလုပ်လုပ်မည် မဟုá€á€ºá€•á€«á‹"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google ပလေး á€á€”်ဆောင်မှုများကá€á€¯ ရယူရန်"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google ပလေး á€á€”်ဆောင်မှုများ ဖွင့်ရန်"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"သင်က Google ပလေး á€á€”်ဆောင်မှုများ မဖွင့်သရွေ့ ဤapp အလုပ်လုပ်မည် မဟုá€á€ºá€•á€«á‹"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google ပလေး á€á€”်ဆောင်မှုများ ဖွင့်ရန်"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google ပလေး á€á€”်ဆောင်မှုများကá€á€¯ မွမ်းမံရန်"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"အန်ဒရွá€á€¯á€€á€º ဆောင်စရာကá€á€¯ မွမ်းမံရန်"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"သင်သည် Google ပလေး á€á€”်ဆောင်မှုများကá€á€¯ မမွမ်းမံသရွေ့ ဤ app အလုပ် လုပ်မည် မဟုá€á€ºá€•á€«á‹"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"သင်က အန်ဒရွá€á€¯á€€á€º ဆောင်စရာ appကá€á€¯ မွမ်းမံ မပေးမá€á€»á€„်း ဒီapp အလုပ်လုပ်မည် မဟုá€á€ºá€•á€«á‹"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ကွန်ရက် အမှား"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google ပလေး á€á€”်ဆောင်မှုများသá€á€¯á€· ဆက်သွယ်ရန် ဒေá€á€¬ á€á€»á€á€á€ºá€†á€€á€ºá€™á€¾á€¯ လá€á€¯á€¡á€•á€ºá€žá€Šá€ºá‹"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"မမှန်သည့် အကောင့်"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"ဤကá€á€›á€á€šá€¬á€™á€¾á€¬ ဖေါ်ပြပါ အကောင့်မရှá€á€•á€«á‹ ကျေးဇူးပြုá အá€á€¼á€¬á€¸ အကောင့်ကá€á€¯ ရွေးပါá‹"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google ပလေး á€á€”်ဆောင်မှုá€á€½á€„် မသá€á€› ပြဿနာ ရှá€á€”ေသည်á‹"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google ပလေး á€á€”်ဆောင်မှုများ"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"သင်á အပလီကေးရှင်း အá€á€»á€á€¯á€·á€€ အားကá€á€¯á€¸á€€á€¼á€žá€Šá€·á€º Google ပလေး á€á€”်ဆောင်မှုများကá€á€¯ သင်á ကá€á€›á€á€šá€¬á€€ မပံ့ပá€á€¯á€¸á€•á€«á‹ အကူအညီရယူရန် ကျေးဇူးပြုပြီး ထုá€á€ºá€œá€¯á€•á€ºá€žá€°á€€á€á€¯ ဆက်သွယ်ပါá‹"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"မွမ်းမံရန်"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"လင်မှá€á€ºá€‘á€á€¯á€¸ á€á€„်"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google ဖြင့် လက်မှá€á€ºá€‘á€á€¯ á€á€„်"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ဖုန်းထဲ ဖွင့်ရန်"</string> +</resources> diff --git a/play-services-base/res/values-nb/common_strings.xml b/play-services-base/res/values-nb/common_strings.xml new file mode 100644 index 0000000..646f094 --- /dev/null +++ b/play-services-base/res/values-nb/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play Tjenester-feil"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"En app krever installasjon av Google Play Tjenester."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"En app krever at Google Play Tjenester oppdateres."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"En app krever en oppdatering av Android Wear-appen."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"En app krever Google Play Tjenester for Ã¥ aktiveres."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Forespurt av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Installer Google Play Tjenester"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert pÃ¥ telefonen din."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert pÃ¥ nettbrettet ditt."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Installer Google Play Tjenester"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktiver Google Play Tjenester"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Denne appen fungerer ikke med mindre du aktiverer Google Play Tjenester."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktiver Google Play Tjenester"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Oppdater Google Play Tjenester"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Oppdater Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Denne appen kan ikke kjøres før du oppdaterer Google Play Tjenester."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Denne appen kjører ikke med mindre du oppdaterer Android Wear-appen."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Nettverksfeil"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Du mÃ¥ ha datatilkobling for Ã¥ koble deg til Google Play-tjenester."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ugyldig konto"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Den angitte kontoen finnes ikke pÃ¥ enheten. Velg en annen konto."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Det oppsto et ukjent problem med Google Play Tjenester."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-tjenester"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play Tjenester, som noen av appene er avhengige av, støttes ikke av enheten. Ta kontakt med produsenten for Ã¥ fÃ¥ hjelp."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Oppdater"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Logg pÃ¥"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Logg inn med Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ã…pne pÃ¥ telefonen"</string> +</resources> diff --git a/play-services-base/res/values-ne-rNP/common_strings.xml b/play-services-base/res/values-ne-rNP/common_strings.xml new file mode 100644 index 0000000..5b3d605 --- /dev/null +++ b/play-services-base/res/values-ne-rNP/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play सेवाहरूका तà¥à¤°à¥à¤Ÿà¤¿"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Google Play सेवाहरू सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ गरà¥à¤¨ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— आवशà¥à¤¯à¤• हà¥à¤¨à¥à¤›à¥¤"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Google Play सेवाहरू अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¨ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— आवशà¥à¤¯à¤• हà¥à¤¨à¥à¤›à¥¤"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android उपयोग अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— लाई अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¨ à¤à¤• अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—को आवशà¥à¤¯à¤• छ।"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Google Play का सेवाहरू सकà¥à¤·à¤® गरà¥à¤¨ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— आवशà¥à¤¯à¤• हà¥à¤¨à¥à¤›à¥¤"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> दà¥à¤µà¤¾à¤°à¤¾ अनà¥à¤°à¥‹à¤§ गरियो"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play सेवाहरू पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"यो अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— Google Play सेवाहरू बिना चलà¥à¤¦à¥ˆà¤¨ जà¥à¤¨ तपाईà¤à¤•à¥‹ फोनमा छैन।"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"यो अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— Google Play सेवाहरू बिना चलà¥à¤¦à¥ˆà¤¨ जà¥à¤¨ तपाईà¤à¤•à¥‹ टà¥à¤¯à¤¾à¤¬à¥à¤²à¥‡à¤Ÿà¤®à¤¾ छैन।"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play सेवाहरू पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play सेवाहरू सकà¥à¤·à¤® पारà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"तपाईà¤à¤²à¥‡ Google Play सेवाहरूलाई सकà¥à¤·à¤® नपारेसमà¥à¤® यस अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ले काम गरà¥à¤¦à¥ˆà¤¨à¥¤"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play सेवाहरू सकà¥à¤·à¤® पारà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play सेवाहरू अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android उपयोग अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"तपाईà¤à¤²à¥‡ Google Play सेवाहरू अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• नगरेसमà¥à¤® यो अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— चलà¥à¤¨à¥‡ छैन।"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android उपयोग अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• नगरेसमà¥à¤® यो अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ले कारà¥à¤¯ गरà¥à¤¨à¥‡ छैन।"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"नेटवरà¥à¤• तà¥à¤°à¥à¤Ÿà¤¿"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"à¤à¤‰à¤Ÿà¤¾ डेटा जडान Google पà¥à¤²à¥‡ सेवाहरूसà¤à¤— जडित गरà¥à¤¨ आवशà¥à¤¯à¤•à¤¤à¤¾ छ।"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"अमानà¥à¤¯ खाता"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ खाता यो उपकरणमा छैन। कृपया à¤à¤‰à¤Ÿà¤¾ अलग खाता चयन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play सेवाहरूको अजà¥à¤žà¤¾à¤¤ सवाल"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play सेवाहरू"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play सेवाहरूसà¤à¤— à¤à¤° परà¥à¤¨à¥‡ केही तपाईà¤à¤•à¤¾ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—हरू तपाईà¤à¤•à¥‹ उपकरणले समरà¥à¤¥à¤¨ गरà¥à¤¦à¥ˆà¤¨à¥¤ कृपया सहयोगका लागि निमारà¥à¤¤à¤¾à¤¸à¤à¤— समà¥à¤ªà¤°à¥à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"साइन इन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"गà¥à¤—लका साथ साइन इन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"फोनमा खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string> +</resources> diff --git a/play-services-base/res/values-nl/common_strings.xml b/play-services-base/res/values-nl/common_strings.xml new file mode 100644 index 0000000..653e408 --- /dev/null +++ b/play-services-base/res/values-nl/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Fout met Google Play-services"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Google Play-services moet zijn geïnstalleerd voor een app."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Google Play-services moet worden geüpdatet voor een app."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Er is een update van de Android Wear-app vereist voor een bepaalde app."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Google Play-services moet zijn ingeschakeld voor een app."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Aangevraagd door <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play-services ophalen"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw telefoon."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play-services ophalen"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play-services inschakelen"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Deze app werkt niet, tenzij u Google Play-services inschakelt."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play-services inschak."</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play-services updaten"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear bijwerken"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Deze app kan niet worden uitgevoerd, tenzij u Google Play-services updatet."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Deze app wordt niet uitgevoerd, tenzij u de Android Wear-app bijwerkt."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Netwerkfout"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Er is een gegevensverbinding nodig om verbinding te kunnen maken met Google Play-services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ongeldig account"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Het gespecificeerde account bestaat niet op dit apparaat. Kies een ander account."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Onbekend probleem met Google Play-services."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play-services, dat vereist is voor een aantal van uw applicaties, wordt niet ondersteund door uw apparaat. Neem contact op met de fabrikant voor ondersteuning."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Updaten"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Inloggen"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Inloggen met Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Openen op telefoon"</string> +</resources> diff --git a/play-services-base/res/values-pl/common_strings.xml b/play-services-base/res/values-pl/common_strings.xml new file mode 100644 index 0000000..20d687a --- /dev/null +++ b/play-services-base/res/values-pl/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"BÅ‚Ä…d UsÅ‚ug Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Aplikacja wymaga zainstalowania UsÅ‚ug Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Aplikacja wymaga zaktualizowania UsÅ‚ug Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Aplikacja wymaga aktualizacji do Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Aplikacja wymaga wÅ‚Ä…czenia UsÅ‚ug Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Żądanie z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Pobierz UsÅ‚ugi Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ta aplikacja nie bÄ™dzie dziaÅ‚ać bez UsÅ‚ug Google Play, których nie masz na telefonie."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ta aplikacja nie bÄ™dzie dziaÅ‚ać bez UsÅ‚ug Google Play, których nie masz na tablecie."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Pobierz UsÅ‚ugi Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"WÅ‚Ä…cz UsÅ‚ugi Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ta aplikacja nie bÄ™dzie dziaÅ‚ać, jeÅ›li nie wÅ‚Ä…czysz UsÅ‚ug Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"WÅ‚Ä…cz UsÅ‚ugi Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Aktualizuj UsÅ‚ugi Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Zaktualizuj Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ta aplikacja nie bÄ™dzie dziaÅ‚ać, jeÅ›li nie zaktualizujesz UsÅ‚ug Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ta aplikacja nie bÄ™dzie dziaÅ‚ać, jeÅ›li nie zaktualizujesz aplikacji Google Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"BÅ‚Ä…d sieci"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Korzystanie z usÅ‚ug Google Play wymaga poÅ‚Ä…czenia z internetem."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"NieprawidÅ‚owe konto"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Podanego konta nie ma na tym urzÄ…dzeniu. Wybierz inne konto."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Nieznany problem z UsÅ‚ugami Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"UsÅ‚ugi Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"UsÅ‚ugi Google Play, od których zależy dziaÅ‚anie niektórych aplikacji, nie sÄ… obsÅ‚ugiwane na Twoim urzÄ…dzeniu. Skontaktuj siÄ™ z producentem, by uzyskać pomoc."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Aktualizuj"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Zaloguj siÄ™"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Zaloguj siÄ™ przez Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Otwórz na telefonie"</string> +</resources> diff --git a/play-services-base/res/values-pt-rBR/common_strings.xml b/play-services-base/res/values-pt-rBR/common_strings.xml new file mode 100644 index 0000000..8c0b573 --- /dev/null +++ b/play-services-base/res/values-pt-rBR/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Erro do Google Play Services"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Um app requer a instalação do Google Play Services."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Um app requer a atualização do Google Play Services."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Um app exige uma atualização do app Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Um app requer a ativação do Google Play Services."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Solicitado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Instale o Google Play Services"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Este app não funciona sem o Google Play Services, que não está instalado em seu telefone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Este app não funciona sem o Google Play Services, que não está instalado em seu tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Instalar o Google Play Services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ative o Google Play Services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Este app só funciona com o Google Play Services ativado."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ativar o Google Play Services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atualize o Google Play Services"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Atualizar o Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Este app só funciona com uma versão atualizada do Google Play Services."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Este app só funciona com uma versão atualizada do app Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro na rede"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necessária uma conexão de dados para conectar ao Google Play Services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta inválida"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada não existe no dispositivo. Escolha outra conta."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema desconhecido com o Google Play Services."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Play Services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"O Google Play Services, necessário para alguns dos apps, não é compatÃvel com seu dispositivo. Entre em contato com o fabricante para obter assistência."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atualizar"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Login"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Fazer login com o Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Abrir no smartphone"</string> +</resources> diff --git a/play-services-base/res/values-pt-rPT/common_strings.xml b/play-services-base/res/values-pt-rPT/common_strings.xml new file mode 100644 index 0000000..7c1a601 --- /dev/null +++ b/play-services-base/res/values-pt-rPT/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Erro dos Serviços do Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Uma aplicação necessita da instalação dos Serviços do Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Uma aplicação necessita da atualização dos Serviços do Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Uma aplicação requer uma atualização da aplicação Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Uma aplicação necessita da ativação dos Serviços do Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Pedida por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Obter serviços do Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu telemóvel."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Obter serviços do Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ativar serviços do Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Esta aplicação não funcionará enquanto não ativar os serviços do Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ativar serviços do Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atualizar serviços do Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Atualizar Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Esta aplicação não será executada enquanto não atualizar os serviços do Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Esta aplicação não será executada enquanto não atualizar a aplicação Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro de Rede"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necessária uma ligação de dados para se ligar aos Serviços do Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta Inválida"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada não existe neste dispositivo. Escolha uma conta diferente."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema desconhecido nos serviços do Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Serviços do Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Os serviços do Google Play, dos quais dependem algumas das suas aplicações, não são suportados pelo seu dispositivo. Contacte o fabricante para obter assistência."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atualizar"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Inic. ses."</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Inic. sessão com o Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Abrir no telemóvel"</string> +</resources> diff --git a/play-services-base/res/values-pt/common_strings.xml b/play-services-base/res/values-pt/common_strings.xml new file mode 100644 index 0000000..8c0b573 --- /dev/null +++ b/play-services-base/res/values-pt/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Erro do Google Play Services"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Um app requer a instalação do Google Play Services."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Um app requer a atualização do Google Play Services."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Um app exige uma atualização do app Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Um app requer a ativação do Google Play Services."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Solicitado por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Instale o Google Play Services"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Este app não funciona sem o Google Play Services, que não está instalado em seu telefone."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Este app não funciona sem o Google Play Services, que não está instalado em seu tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Instalar o Google Play Services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Ative o Google Play Services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Este app só funciona com o Google Play Services ativado."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Ativar o Google Play Services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Atualize o Google Play Services"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Atualizar o Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Este app só funciona com uma versão atualizada do Google Play Services."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Este app só funciona com uma versão atualizada do app Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Erro na rede"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"É necessária uma conexão de dados para conectar ao Google Play Services."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Conta inválida"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"A conta especificada não existe no dispositivo. Escolha outra conta."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problema desconhecido com o Google Play Services."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Play Services"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"O Google Play Services, necessário para alguns dos apps, não é compatÃvel com seu dispositivo. Entre em contato com o fabricante para obter assistência."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Atualizar"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Login"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Fazer login com o Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Abrir no smartphone"</string> +</resources> diff --git a/play-services-base/res/values-ro/common_strings.xml b/play-services-base/res/values-ro/common_strings.xml new file mode 100644 index 0000000..b75f231 --- /dev/null +++ b/play-services-base/res/values-ro/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Eroare a serviciilor Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"O aplicaÈ›ie necesită instalarea serviciilor Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"O aplicaÈ›ie necesită o actualizare pentru serviciile Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"O aplicaÈ›ie necesită actualizarea aplicaÈ›iei Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"O aplicaÈ›ie necesită activarea serviciilor Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Solicitată de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"DescărcaÅ£i Servicii Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Această aplicaÅ£ie nu poate rula fără Servicii Google Play, care lipsesc de pe telefon."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Această aplicaÅ£ie nu poate rula fără Servicii Google Play, care lipsesc de pe tabletă."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"ObÅ£ineÅ£i Servicii Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"ActivaÅ£i Servicii Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Această aplicaÅ£ie nu va funcÅ£iona decât dacă activaÅ£i Servicii Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"ActivaÅ£i Servicii Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"ActualizaÅ£i Servicii Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"ActualizaÈ›i Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Această aplicaÅ£ie nu poate rula decât dacă actualizaÅ£i Servicii Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Această aplicaÈ›ie nu va rula dacă nu actualizaÈ›i aplicaÈ›ia Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Eroare de reÅ£ea"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Este necesară o conexiune de date pentru a vă conecta la serviciile Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Cont nevalid"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Contul menÈ›ionat nu există pe acest dispozitiv. AlegeÈ›i alt cont."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Problemă necunoscută privind Servicii Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Servicii Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Gadgetul nu acceptă serviciile Google Play, pe care se bazează unele dintre aplicaÈ›ii. Pentru asistență, contactaÈ›i producătorul gadgetului."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"ActualizaÅ£i"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ConectaÈ›i"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"ConectaÈ›i-vă cu Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"DeschideÈ›i pe telefon"</string> +</resources> diff --git a/play-services-base/res/values-ru/common_strings.xml b/play-services-base/res/values-ru/common_strings.xml new file mode 100644 index 0000000..6aab49f --- /dev/null +++ b/play-services-base/res/values-ru/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Ошибка ÑервиÑов Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ ÑƒÑтановить ÑервиÑÑ‹ Google Play"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ ÑервиÑÑ‹ Google Play"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"ТребуетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ приложение Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒ ÑервиÑÑ‹ Google Play"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"ИÑточник запроÑа: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"УÑтановите СервиÑÑ‹ Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñтого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ ÑƒÑтановить СервиÑÑ‹ Google Play."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñтого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ ÑƒÑтановить СервиÑÑ‹ Google Play."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"УÑтановить"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Включите СервиÑÑ‹ Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñтого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒ СервиÑÑ‹ Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Включить"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Обновите СервиÑÑ‹ Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Обновить Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñтого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ СервиÑÑ‹ Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñтого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Ошибка Ñети"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Google Play требуетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ðµ к Ñети."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ÐедейÑтвительный аккаунт"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Ðтого аккаунта нет на уÑтройÑтве. Выберите другой."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° Ñ Ð¡ÐµÑ€Ð²Ð¸Ñами Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"СервиÑÑ‹ Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"СервиÑÑ‹ Google Play, необходимые Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ некоторых приложений, не поддерживаютÑÑ Ð½Ð° вашем уÑтройÑтве. ОбратитеÑÑŒ к производителю."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Обновить"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Войти"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Войти в аккаунт Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Открыть на телефоне"</string> +</resources> diff --git a/play-services-base/res/values-si-rLK/common_strings.xml b/play-services-base/res/values-si-rLK/common_strings.xml new file mode 100644 index 0000000..2ddf0ff --- /dev/null +++ b/play-services-base/res/values-si-rLK/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play සේව෠දà·à·‚ය"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"යෙදුමකට Google Play සේව෠ස්ථà·à¶´à¶±à¶ºà¶šà·Š අවà·à·Šâ€à¶ºà¶º."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"යෙදුමකට Google Play සේවà·à·€à¶±à·Š සඳහ෠යà·à·€à¶à·Šà¶šà·à¶½à·“නයක් අවà·à·Šâ€à¶ºà¶º."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android Wear යෙදුම යà·à·€à¶à·Šà¶šà·à¶½à·“න කිරීමට යෙදුමක් අවà·à·Šâ€à¶ºà¶º."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"යෙදුමකට Google Play සේවà·à·€à¶±à·Š සබලව à¶à·’බීම අවà·à·Šâ€à¶ºà¶º."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> විසින් ඉල්ල෠ඇà¶"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play සේවà·à·€à¶±à·Š ලබ෠ගන්න"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"ඔබගේ දුරකථනයෙන් අස්ථà·à¶±à¶œà¶ වී ඇà¶à·’ Google Play සේවà·à·€à¶±à·Š රහිà¶à·€ මෙම යෙදුම ධà·à·€à¶±à¶º නොවනු ඇà¶."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"ඔබගේ ටà·à¶¶à·Šà¶½à¶§à¶ºà·™à¶±à·Š අස්ථà·à¶±à¶œà¶ වී ඇà¶à·’ Google Play සේවà·à·€à¶±à·Š රහිà¶à·€ මෙම යෙදුම ධà·à·€à¶±à¶º නොවේ."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play සේවà·à·€à¶±à·Š ලබ෠ගන්න"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play සේවà·à·€à¶±à·Š සබල කරන්න"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"ඔබ Google Play සේවà·à·€à¶±à·Š සබල කරන්නේ නම් මිස මෙම යෙදුම à·€à·à¶© නොකරනු ඇà¶."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play සේවà·à·€à¶±à·Š සබල කරන්න"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play සේවà·à·€à¶±à·Š යà·à·€à¶à·Šà¶šà·à¶½à·“න කරන්න"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear යà·à·€à¶à·Šà¶šà·à¶½à·“න කරන්න"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"ඔබ Google Play සේව෠යà·à·€à¶à·Šà¶šà·à¶½à·“න කරන්නේ නම් මිස මෙම යෙදුම ධà·à·€à¶±à¶º නොවේ."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android Wear යෙදුම ඔබ යà·à·€à¶à·Šà¶šà·à¶½à·“න කළේ නà·à¶à·’ නම් මෙම යෙදුම ධà·à·€à¶±à¶º කළ නොහà·à¶š."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ජà·à¶½ දà·à·‚ය"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play සේවà·à·€à¶±à·Š වෙචසබà·à¶³à·“මට දà¶à·Šà¶ සබà·à¶³à·”මක් අවà·à·Šâ€à¶ºà¶º."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"වලංගු නොවන ගිණුම"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"නියම කර දà·à¶šà·Šà·€à·– ගිණුම මෙම උපà·à¶‚ගය මචනොපවà¶à·“. කරුණà·à¶šà¶» වෙනà¶à·Š ගිණුමක් à¶à·à¶»à¶±à·Šà¶±."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play සේවà·à·€à¶±à·Š සමග නොදන්න෠ගà·à¶§à¶½à·”වක්."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play සේවà·"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"ඔබගේ සමහර යෙදුම් විà·à·Šà·€à·à·ƒà¶º à¶à¶¶à¶±, Google Play සේවà·à·€à¶±à·Šà¶§, ඔබගේ උපà·à¶‚ගය සහà·à¶º නොදක්වයි. කරුණà·à¶šà¶» සහà·à¶º සඳහ෠නිෂ්පà·à¶¯à¶šà¶ºà· අමà¶à¶±à·Šà¶±."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"යà·à·€à¶à·Šà¶šà·à¶½à·“න කරන්න"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"පිවිසෙන්න"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google සමගින් පුරනය වන්න"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"දුරකථනය à¶à·”à·… විවෘචකරන්න"</string> +</resources> diff --git a/play-services-base/res/values-sk/common_strings.xml b/play-services-base/res/values-sk/common_strings.xml new file mode 100644 index 0000000..a44a4bf --- /dev/null +++ b/play-services-base/res/values-sk/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Chyba služieb Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Aplikácia vyžaduje inÅ¡taláciu služieb Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Aplikácia vyžaduje aktualizáciu služieb Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Niektorá aplikácia vyžaduje aktualizáciu aplikácie Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Aplikácia vyžaduje povolenie služieb Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Vyžiadané aplikáciou <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"InÅ¡talovaÅ¥ služby Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v telefóne nemáte."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v tablete nemáte."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"InÅ¡talovaÅ¥ služby Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"PovoliÅ¥ služby Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Táto aplikácia bude fungovaÅ¥ až po povolenà služieb Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"PovoliÅ¥ služby Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"AktualizovaÅ¥ služby Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Aktualizujte aplikáciu Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Túto aplikáciu bude možné spustiÅ¥ až po aktualizácii služieb Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Táto aplikácia bude fungovaÅ¥ až po aktualizácii aplikácie Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Chyba siete"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Pripojenie k službám Google Play si vyžaduje dátové pripojenie."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Neplatný úÄet"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Zadaný úÄet v tomto zariadenà neexistuje. Vyberte iný úÄet."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Neznámy problém so službami Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Služby Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Niektoré vaÅ¡e aplikácie vyžadujú služby Google Play, ktoré vo vaÅ¡om zariadenà nie sú podporované. Ak potrebujete pomoc, kontaktujte výrobcu."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"AktualizovaÅ¥"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"PrihlásiÅ¥ sa"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"PrihlásiÅ¥ sa do úÄtu Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"OtvoriÅ¥ na telefóne"</string> +</resources> diff --git a/play-services-base/res/values-sl/common_strings.xml b/play-services-base/res/values-sl/common_strings.xml new file mode 100644 index 0000000..1af1f02 --- /dev/null +++ b/play-services-base/res/values-sl/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Napaka storitev Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Za delovanje aplikacije morate namestiti storitve Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Za delovanje aplikacije morate posodobiti storitve Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Aplikacija zahteva posodobitev aplikacije Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Za delovanje aplikacije morate omogoÄiti storitve Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Zahteva aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Namestite storitve Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v telefonu."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v tabliÄnem raÄunalniku."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Namestite storitve Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"OmogoÄite storitve Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Aplikacija ne bo delovala, Äe ne omogoÄite storitev Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"OmogoÄite storitve Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Posodobite storitve Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Posodobitev aplikacije Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ta aplikacija ne deluje, Äe ne posodobite storitev Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ta aplikacije ne deluje, Äe ne posodobite aplikacije Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Omrežna napaka"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Za povezavo s storitvami Google Play potrebujete internetno povezavo."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Neveljaven raÄun"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"V tej napravi ne obstaja navedeni raÄun. Izberite drugega."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Neznana težava s storitvami Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Storitve Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"VaÅ¡a naprava na podpira storitev Google Play, ki jih potrebujejo nekatere od vaÅ¡ih aplikacij. Za pomoÄ se obrnite na izdelovalca."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Posodobi"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Prijava"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Prijavite se v Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Odpiranje v telefonu"</string> +</resources> diff --git a/play-services-base/res/values-sr/common_strings.xml b/play-services-base/res/values-sr/common_strings.xml new file mode 100644 index 0000000..c6d6976 --- /dev/null +++ b/play-services-base/res/values-sr/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Грешка Google Play уÑлуга"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Ðпликација захтева инÑталацију Google Play уÑлуга."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Ðпликација захтева ажурирање Google Play уÑлуга."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ðпликација захтева ажурирање апликације Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ðпликација захтева да Google Play уÑлуге буду омогућене."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Захтева <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Преузимање Google Play уÑлуга"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ова апликација не може да Ñе покрене без Google Play уÑлуга, које недоÑтају на телефону."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ова апликација не може да Ñе покрене без Google Play уÑлуга, које недоÑтају на таблету."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Преузми Google Play уÑлуге"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Омогућавање Google Play уÑлуга"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ова апликација неће функциониÑати ако не омогућите Google Play уÑлуге."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Омогући Google Play уÑлуге"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Ðжурирање Google Play уÑлуга"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Ðжурирајте Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ова апликација не може да Ñе покрене ако не ажурирате Google Play уÑлуге."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ова апликација не може да Ñе покрене ако не ажурирате апликацију Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Грешка на мрежи"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"За повезивање Ñа Google Play уÑлугама потребна је веза за Ð¿Ñ€ÐµÐ½Ð¾Ñ Ð¿Ð¾Ð´Ð°Ñ‚Ð°ÐºÐ°."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ðеважећи налог"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Ðаведени налог не поÑтоји на овом уређају. Одаберите други налог."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ðепознат проблем Ñа Google Play уÑлугама."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play уÑлуге"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Google Play уÑлуге, које Ñу потребне за функциониÑање неких од апликација, ниÑу подржане на уређају. Контактирајте произвођача да биÑте добили помоћ."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Ðжурирај"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Пријави ме"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Пријави ме преко Google-а"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Отвори на телефону"</string> +</resources> diff --git a/play-services-base/res/values-sv/common_strings.xml b/play-services-base/res/values-sv/common_strings.xml new file mode 100644 index 0000000..22e459c --- /dev/null +++ b/play-services-base/res/values-sv/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Fel pÃ¥ Google Play-tjänster"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Google Play-tjänster mÃ¥ste installeras för att en app ska fungera."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Google Play-tjänster mÃ¥ste uppdateras för en app ska fungera."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"En app kräver att appen Android Wear uppdateras."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Google Play-tjänster mÃ¥ste aktiveras för att en app ska fungera."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Begärdes av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Hämta Google Play Tjänster"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Den här appen kan inte köras utan Google Play Tjänster, som saknas pÃ¥ mobilen."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Den här appen kan inte köras utan Google Play Tjänster, som saknas pÃ¥ surfplattan."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Hämta Google Play Tjänster"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Aktivera Google Play Tjänster"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Du mÃ¥ste aktivera Google Play Tjänster för att den här appen ska fungera."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Aktivera Google Play Tjänster"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Uppdatera Google Play Tjänster"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Uppdatera Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Du mÃ¥ste uppdatera Google Play Tjänster innan du kan köra den här appen."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Om du inte uppdaterar appen Android Wear kan den här appen inte köras."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Nätverksfel"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"En dataanslutning krävs för att ansluta till Google Plays tjänster."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Ogiltigt konto"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Det angivna kontot finns inte pÃ¥ den här enheten. Välj ett annat konto."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Okänt problem med Google Play Tjänster"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play-tjänster"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"NÃ¥gra av dina appar använder Google Play-tjänster som inte stöds av din enhet. Kontakta tillverkaren om du vill ha hjälp."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Uppdatera"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Logga in"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Logga in med Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Öppna pÃ¥ mobilen"</string> +</resources> diff --git a/play-services-base/res/values-sw/common_strings.xml b/play-services-base/res/values-sw/common_strings.xml new file mode 100644 index 0000000..982eb4a --- /dev/null +++ b/play-services-base/res/values-sw/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Hitilafu kwenye huduma za Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Programu inahitaji usakinishaji wa huduma za Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Programu inahitaji toleo jipya la huduma za Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Programu inahitaji sasisho kwa programu ya Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Programu inahitaji huduma za Google Play ili iwashwe."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Imeombwa na <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Pata huduma za Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Programu hii haiwezi kuendeshwa bila huduma za Google Play, ambazo hazipo kwenye simu yako."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Programu hii haiwezi kufanya kazi bila huduma za Google Play, ambazo hazipatikani kwenye kompyuta kibao yako."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Pata huduma za Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Wezesha huduma za Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Programu hii haitafanya kazi mpaka utakapowezesha huduma za Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Wezesha huduma za Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Sasisha huduma za Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Sasisha Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Programu hii haiwezi kuendeshwa mpaka utakaposasisha huduma za Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Programu hii haitaendeshwa usiposasisha programu ya Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Hitilafu ya Mtandao"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Muunganisho wa data unahitajika ili kuunganisha kwenye huduma za Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Akaunti Batili"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Akaunti iliyobainishwa haipo kwenye kifaa hiki. Tafadhali chagua akaunti tofauti."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Suala lisilojulikana na huduma za Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Huduma za Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Huduma za Google Play, ambazo baadhi ya programu zako zinategemea, si linganifu na kifaa chako. Tafadhali wasiliana na mtengenezaji kwa usaidizi."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Sasisha"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Ingia"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Ingia ukitumia Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Fungua kwenye simu"</string> +</resources> diff --git a/play-services-base/res/values-ta-rIN/common_strings.xml b/play-services-base/res/values-ta-rIN/common_strings.xml new file mode 100644 index 0000000..f026b82 --- /dev/null +++ b/play-services-base/res/values-ta-rIN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play சேவைகள௠பிழை"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"பயனà¯à®ªà®¾à®Ÿà®¾à®©à®¤à¯ Google Play சேவைகள௠நிறà¯à®µ கேடà¯à®•à®¿à®±à®¤à¯."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"பயனà¯à®ªà®¾à®Ÿà®¾à®©à®¤à¯ Google Play சேவைகளà¯à®•à¯à®•à®¾à®© பà¯à®¤à¯à®ªà¯à®ªà®¿à®ªà¯à®ªà¯ˆà®•à¯ கேடà¯à®•à®¿à®±à®¤à¯."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Android வியரà¯à®•à¯à®•à¯à®ªà¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆà®ªà¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"பயனà¯à®ªà®¾à®Ÿà®¾à®©à®¤à¯ Google Play சேவைகள௠இயகà¯à®•à®•à¯ கேடà¯à®•à®¿à®±à®¤à¯."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆல௠கோரபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play சேவைகளைப௠பெறà¯à®•"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"உஙà¯à®•à®³à¯ தொலைபேசியில௠இலà¯à®²à®¾à®¤ Google Play சேவைகள௠இலà¯à®²à®¾à®®à®²à¯ இநà¯à®¤à®ªà¯ பயனà¯à®ªà®¾à®Ÿà¯ இயஙà¯à®•à®¾à®¤à¯."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"உஙà¯à®•à®³à¯ டேபà¯à®²à¯†à®Ÿà¯à®Ÿà®¿à®²à¯ இலà¯à®²à®¾à®¤ Google Play சேவைகள௠இலà¯à®²à®¾à®®à®²à¯ இநà¯à®¤à®ªà¯ பயனà¯à®ªà®¾à®Ÿà¯ இயஙà¯à®•à®¾à®¤à¯."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play சேவைகளைப௠பெறà¯à®•"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play சேவைகளை இயகà¯à®•à¯"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"நீஙà¯à®•à®³à¯ Google Play சேவைகளை இயகà¯à®•à¯à®®à¯à®µà®°à¯ˆ இநà¯à®¤à®ªà¯ பயனà¯à®ªà®¾à®Ÿà¯ வேலை செயà¯à®¯à®¾à®¤à¯."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play சேவைகளை இயகà¯à®•à¯"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play சேவைகளைப௠பà¯à®¤à¯à®ªà¯à®ªà®¿"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android வியரைப௠பà¯à®¤à¯à®ªà¯à®ªà®¿"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"நீஙà¯à®•à®³à¯ Google Play சேவைகளைப௠பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à¯à®®à¯à®µà®°à¯ˆ இநà¯à®¤à®ªà¯ பயனà¯à®ªà®¾à®Ÿà¯ இயஙà¯à®•à®¾à®¤à¯."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android வியரà¯à®•à¯à®•à¯à®ªà¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à¯à®®à¯ வரை, பயனà¯à®ªà®¾à®Ÿà¯ செயலà¯à®ªà®Ÿà®¾à®¤à¯."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"பிணைய பிழை"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play சேவைகளில௠இணைகà¯à®• தரவ௠இணைபà¯à®ªà¯ தேவை."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"தவறான கணகà¯à®•à¯"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿ கணகà¯à®•à¯ இலà¯à®²à¯ˆ. வேற௠கணகà¯à®•à¯ˆà®¤à¯ தேரà¯à®µà¯ செயà¯à®¯à®µà¯à®®à¯."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play சேவைகளில௠அறியபà¯à®ªà®Ÿà®¾à®¤ சிகà¯à®•à®²à¯ உளà¯à®³à®¤à¯."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play சேவைகளà¯"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"உஙà¯à®•à®³à¯ பயனà¯à®ªà®¾à®Ÿà¯à®•à®³à®¿à®²à¯ சில சாரà¯à®¨à¯à®¤à¯à®³à¯à®³ Google Play சேவைகளை உஙà¯à®•à®³à¯ சாதனம௠ஆதரிகà¯à®•à®µà®¿à®²à¯à®²à¯ˆ. உதவிகà¯à®•à¯ உறà¯à®ªà®¤à¯à®¤à®¿à®¯à®¾à®³à®°à¯ˆà®¤à¯ தொடரà¯à®ªà¯à®•à¯Šà®³à¯à®³à®µà¯à®®à¯."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"பà¯à®¤à¯à®ªà¯à®ªà®¿"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"உளà¯à®¨à¯à®´à¯ˆà®•"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google மூலம௠உளà¯à®¨à¯à®´à¯ˆ"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ஃபோனில௠திற"</string> +</resources> diff --git a/play-services-base/res/values-te-rIN/common_strings.xml b/play-services-base/res/values-te-rIN/common_strings.xml new file mode 100644 index 0000000..b680d4c --- /dev/null +++ b/play-services-base/res/values-te-rIN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play సేవల లోపం"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"à°’à°• à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à°¿à°•à°¿ Google Play సేవల యొకà±à°• ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à±‡à°·à°¨à± అవసరం."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"à°’à°• à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à°¿à°•à°¿ Google Play సేవలౠనవీకరించబడటం అవసరం."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"à°’à°• à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à°¿à°•à°¿ Android Wear à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à±à°¨à°¿ నవీకరించడం అవసరం."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"à°’à°• à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à°¿à°•à°¿ Google Play సేవలౠపà±à°°à°¾à°°à°‚à°à°¿à°‚చబడాలి."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> à°¦à±à°µà°¾à°°à°¾ à°…à°à±à°¯à°°à±à°¥à°¿à°‚చబడింది"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play సేవలనౠపొందండి"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"à°ˆ à°…à°¨à±à°µà°°à±à°¤à°¨à°‚ Google Play సేవలౠలేకà±à°‚à°¡à°¾ అమలౠకాదà±, à°† సేవలౠమీ ఫోనà±â€Œà°²à±‹ లేవà±."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"à°ˆ à°…à°¨à±à°µà°°à±à°¤à°¨à°‚ Google Play సేవలౠలేకà±à°‚à°¡à°¾ అమలౠకాదà±, à°† సేవలౠమీ టాబà±à°²à±†à°Ÿà±â€Œà°²à±‹ లేవà±."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play సేవలనౠపొందండి"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play సేవలనౠపà±à°°à°¾à°°à°‚à°à°¿à°‚à°šà±"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"మీరౠGoogle Play సేవలనౠపà±à°°à°¾à°°à°‚à°à°¿à°¸à±à°¤à±‡ మినహా à°ˆ à°…à°¨à±à°µà°°à±à°¤à°¨à°‚ పని చేయదà±."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play సేవలనౠపà±à°°à°¾à°°à°‚à°à°¿à°‚à°šà±"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play సేవలనౠనవీకరించండి"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wearని నవీకరించండి"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"మీరౠGoogle Play సేవలనౠనవీకరిసà±à°¤à±‡ మినహా à°ˆ à°…à°¨à±à°µà°°à±à°¤à°¨à°‚ అమలౠకాదà±."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"మీరౠAndroid Wear à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à±à°¨à°¿ నవీకరించకపోతే à°ˆ à°…à°¨à±à°µà°°à±à°¤à°¨à°‚ అమలౠకాదà±."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"నెటà±â€Œà°µà°°à±à°•à± లోపం"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play సేవలకౠకనెకà±à°Ÿà± చేయడానికి డేటా కనెకà±à°·à°¨à± అవసరం."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"చెలà±à°²à°¨à°¿ ఖాతా"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"పేరà±à°•à±Šà°¨à±à°¨ ఖాతా à°ˆ పరికరంలో లేదà±. దయచేసి వేరొక ఖాతానౠఎంచà±à°•à±‹à°‚à°¡à°¿."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play సేవలతో తెలియని సమసà±à°¯."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play సేవలà±"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"మీ à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°²à±à°²à±‹ కొనà±à°¨à°¿ ఆధారపడే Google Play సేవలకౠమీ పరికరంలో మదà±à°¦à°¤à± లేదà±. దయచేసి సహాయం కోసం తయారీదారà±à°¨à± సంపà±à°°à°¦à°¿à°‚à°šà°‚à°¡à°¿."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"నవీకరించà±"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"సైనౠఇనౠచేయి"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Googleతో సైనౠఇనౠచేయి"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"ఫోనà±â€Œà°²à±‹ తెరవండి"</string> +</resources> diff --git a/play-services-base/res/values-th/common_strings.xml b/play-services-base/res/values-th/common_strings.xml new file mode 100644 index 0000000..00d3654 --- /dev/null +++ b/play-services-base/res/values-th/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"ข้à¸à¸œà¸´à¸”พลาดขà¸à¸‡à¸šà¸£à¸´à¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันหนึ่งจำเป็นต้à¸à¸‡à¸¡à¸µà¸à¸²à¸£à¸•à¸´à¸”ตั้งบริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันหนึ่งจำเป็นต้à¸à¸‡à¸¡à¸µà¸à¸²à¸£à¸à¸±à¸›à¹€à¸”ตสำหรับบริà¸à¸²à¸£ Google Play"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันรายà¸à¸²à¸£à¸«à¸™à¸¶à¹ˆà¸‡à¸•à¹‰à¸à¸‡à¸à¸²à¸£à¹ƒà¸«à¹‰à¸à¸±à¸›à¹€à¸”ตà¹à¸à¸› Android Wear"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันหนึ่งจำเป็นต้à¸à¸‡à¸¡à¸µà¸šà¸£à¸´à¸à¸²à¸£ Google Play เพื่à¸à¹€à¸›à¸´à¸”ใช้งาน"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"ขà¸à¹‚ดย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"รับบริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันนี้จะไม่ทำงานหาà¸à¹„ม่มีบริà¸à¸²à¸£ Google Play ซึ่งไม่มีในโทรศัพท์ขà¸à¸‡à¸„ุณ"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันนี้จะไม่ทำงานหาà¸à¹„ม่มีบริà¸à¸²à¸£ Google Play ซึ่งไม่มีในà¹à¸—็บเล็ตขà¸à¸‡à¸„ุณ"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"รับบริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"เปิดใช้งานบริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันนี้จะไม่ทำงานจนà¸à¸§à¹ˆà¸²à¸„ุณจะเปิดใช้งานบริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"เปิดใช้งานบริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"à¸à¸±à¸›à¹€à¸”ตบริà¸à¸²à¸£ Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"à¸à¸±à¸›à¹€à¸”ต Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"à¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันนี้จะไม่ทำงานจนà¸à¸§à¹ˆà¸²à¸„ุณจะà¸à¸±à¸›à¹€à¸”ตบริà¸à¸²à¸£ Google Play"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"à¹à¸à¸›à¸™à¸µà¹‰à¸ˆà¸°à¹„ม่ทำงานจนà¸à¸§à¹ˆà¸²à¸„ุณจะà¸à¸±à¸›à¹€à¸”ตà¹à¸à¸› Android Wear"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"ข้à¸à¸œà¸´à¸”พลาดขà¸à¸‡à¹€à¸„รืà¸à¸‚่าย"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"ต้à¸à¸‡à¸¡à¸µà¸à¸²à¸£à¹€à¸‚ื่à¸à¸¡à¸•à¹ˆà¸à¸‚้à¸à¸¡à¸¹à¸¥à¹€à¸žà¸·à¹ˆà¸à¹€à¸Šà¸·à¹ˆà¸à¸¡à¸•à¹ˆà¸à¸à¸±à¸šà¸šà¸£à¸´à¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"บัà¸à¸Šà¸µà¹„ม่ถูà¸à¸•à¹‰à¸à¸‡"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"บัà¸à¸Šà¸µà¸—ี่ระบุไม่มีà¸à¸¢à¸¹à¹ˆà¸šà¸™à¸à¸¸à¸›à¸à¸£à¸“์นี้ โปรดเลืà¸à¸à¸šà¸±à¸à¸Šà¸µà¸à¸·à¹ˆà¸™"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"ปัà¸à¸«à¸²à¸—ี่ไม่รู้จัà¸à¸‚à¸à¸‡à¸šà¸£à¸´à¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"บริà¸à¸²à¸£ Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"บริà¸à¸²à¸£ Google Play ซึ่งใช้งานในบางà¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชัน ไม่ได้รับà¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™à¹‚ดยà¸à¸¸à¸›à¸à¸£à¸“์ขà¸à¸‡à¸„ุณ โปรดติดต่à¸à¸œà¸¹à¹‰à¸œà¸¥à¸´à¸•à¹€à¸žà¸·à¹ˆà¸à¸‚à¸à¸£à¸±à¸šà¸„วามช่วยเหลืà¸"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"à¸à¸±à¸›à¹€à¸”ต"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"ลงชื่à¸à¹ƒà¸Šà¹‰"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"ลงชื่à¸à¹€à¸‚้าใช้ด้วย Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"เปิดบนโทรศัพท์"</string> +</resources> diff --git a/play-services-base/res/values-tl/common_strings.xml b/play-services-base/res/values-tl/common_strings.xml new file mode 100644 index 0000000..1453c64 --- /dev/null +++ b/play-services-base/res/values-tl/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Error sa Mga Serbisyo ng Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Kailangan ng application na i-install ang Mga Serbisyo ng Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Kailangan ng application ng update sa Mga Serbisyo ng Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ang isang application ay nangangailangan ng update sa Android Wear app."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Kailangan ng application na na-enable ang Mga Serbisyo ng Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Hiniling ng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Kumuha ng mga serbisyo ng Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Hindi tatakbo ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong telepono."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Hindi gagana ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong tablet."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Kumuha ng Google Play services"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Paganahin ang Google Play services"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Hindi gagana ang app na ito maliban kung papaganahin mo ang mga serbisyo ng Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Enable Google Play services"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"I-update ang mga serbisyo ng Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"I-update ang Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Hindi gagana ang app na ito maliban kung i-a-update mo ang mga serbisyo ng Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Hindi gagana ang app na ito hanggang sa i-update mo ang Android Wear app."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"May Error sa Network"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Kailangan ng koneksyon ng data upang makakonekta sa mga serbisyo ng Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Di-wasto ang Account"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Hindi umiiral ang tinukoy na account sa device na ito. Mangyaring pumili ng ibang account."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"May hindi alam na isyu sa mga serbisyo ng Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Mga serbisyo ng Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Ang mga serbisyo ng Google Play, kung saan nakadepende ang ilan sa iyong mga application, ay hindi sinusuportahan ng iyong device. Mangyaring makipag-ugnay sa manufacturer para sa tulong."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"I-update"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Sign in"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Mag-sign in sa Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Buksan sa telepono"</string> +</resources> diff --git a/play-services-base/res/values-tr/common_strings.xml b/play-services-base/res/values-tr/common_strings.xml new file mode 100644 index 0000000..74c15b8 --- /dev/null +++ b/play-services-base/res/values-tr/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play Hizmetleri hatası"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Bir uygulama, Google Play hizmetlerinin yüklenmesini gerektiriyor."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Bir uygulama, Google Play Hizmetleri için bir güncelleme gerektiriyor."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Bir uygulama, Android Wear uygulamasında güncelleme yapılmasını gerektiriyor."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Bir uygulama, Google Play Hizmetleri\'nin etkin olmasını gerektiriyor."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Ä°stekte bulunan: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play hizmetlerini edinin"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Google Play Hizmetleri telefonunuzda yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Google Play Hizmetleri tabletinizde yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play hizmetlerini edin"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play hizmetlerini etkinleÅŸtir"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Bu uygulama, Google Play Hizmetleri etkinleÅŸtirilmeden çalışmaz"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play hizmetlerini etkinleÅŸtir"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play hizmetlerini güncelle"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear\'ı Güncelle"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Bu uygulama Google Play Hizmetleri güncellenmeden çalışmaz."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Android Wear uygulaması güncelleninceye kadar bu uygulama çalışmayacak."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"AÄŸ Hatası"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play hizmetlerine baÄŸlanmak için bir veri baÄŸlantısı gerekiyor."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Geçersiz Hesap"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Belirtilen hesap bu cihazda mevcut deÄŸil. Lütfen farklı bir hesap seçin."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play hizmetleriyle ilgili bilinmeyen sorun."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play hizmetleri"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Cihazınız, uygulamalarınızdan bazıları için gerekli olan Google Play hizmetlerini desteklemiyor. Lütfen yardım için üreticiyle iletiÅŸim kurun."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Güncelle"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Oturum aç"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google\'da oturum aç"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Telefonda aç"</string> +</resources> diff --git a/play-services-base/res/values-uk/common_strings.xml b/play-services-base/res/values-uk/common_strings.xml new file mode 100644 index 0000000..65b7611 --- /dev/null +++ b/play-services-base/res/values-uk/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Помилка ÑервіÑів Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Щоб додаток працював, потрібно вÑтановити ÑервіÑи Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Щоб додаток працював, потрібно оновити ÑервіÑи Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ð”Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ додатка потрібно оновити Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Щоб додаток працював, потрібно ввімкнути ÑервіÑи Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Запит від додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"УÑтановіть ÑервіÑи Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° не запуÑтитьÑÑ Ð±ÐµÐ· Google Play ПоÑлуг, Ñких немає у вашому телефоні."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° не запуÑтитьÑÑ Ð±ÐµÐ· Google Play ПоÑлуг, Ñких немає на вашому планшетному ПК."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"УÑтановити ÑервіÑи Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Увімкніть ÑервіÑи Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Цей додаток не працюватиме, доки ви не ввімкнете ÑервіÑи Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Увімкнути ÑервіÑи Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Оновіть ÑервіÑи Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Оновити Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Цей додаток не запуÑтитьÑÑ, доки ви не оновите ÑервіÑи Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Цей додаток запуÑтитьÑÑ, лише коли ви оновите Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Помилка мережі"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Ð”Ð»Ñ Ð¿Ñ–Ð´â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ ÑервіÑів Google Play потрібне Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"ÐедійÑний обліковий запиÑ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Указаний обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ðµ Ñ–Ñнує на цьому приÑтрої. Виберіть інший обліковий запиÑ."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Ðевідома проблема із ÑервіÑами Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"СервіÑи Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Ваш приÑтрій не підтримує СервіÑи Google Play, від Ñких залежить робота деÑких програм. ЗвернітьÑÑ Ð¿Ð¾ допомогу до виробника."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Оновити"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Увійти"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Увійти в обл.Ð·Ð°Ð¿Ð¸Ñ Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Відкрити на телефоні"</string> +</resources> diff --git a/play-services-base/res/values-ur-rPK/common_strings.xml b/play-services-base/res/values-ur-rPK/common_strings.xml new file mode 100644 index 0000000..3ae6c76 --- /dev/null +++ b/play-services-base/res/values-ur-rPK/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"â€Google Play سروسز Ú©ÛŒ خرابی"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"â€Ø§ÛŒÚ© ایپلیکیشن کیلئے Google Play سروسز کا انسٹال Ûونا ضروری ÛÛ’Û”"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"â€Ø§ÛŒÚ© ایپلیکیشن کیلئے Google Play سروسز کیلئے ایک اپ ڈیٹ ضروری ÛÛ’Û”"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"â€Ø§ÛŒÚ© اپیلیکیشن Ú©Ùˆ Android Wear ایپ کیلئے ایک اپ ڈیٹ درکار ÛÛ’Û”"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"â€Ø§ÛŒÚ© ایپلیکیشن کیلئے Google Play سروسز کا Ùعال Ûونا ضروری ÛÛ’Û”"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g> Ú©Û’ ذریعے درخواست Ú©ÛŒ گئی"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"â€Google Play سروسز Øاصل کریں"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"â€ÛŒÛ ایپ Google Play سروسز Ú©Û’ بغیر Ù†Ûیں Ú†Ù„Û’ گی، جو آپ Ú©Û’ Ùون سے غائب ÛÛ’Û”"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"â€ÛŒÛ ایپ Google Play سروسز Ú©Û’ بغیر Ù†Ûیں Ú†Ù„Û’ گی، جو آپ Ú©Û’ ٹیبلیٹ سے غائب ÛÛ’Û”"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"â€Google Play سروسز Øاصل کریں"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"â€Google Play سروسز Ùعال کریں"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"â€ÛŒÛ ایپ تب تک کام Ù†Ûیں کرے Ú¯ÛŒ جب تک Ú©Û Ø¢Ù¾ Google Play سروسز Ùعال Ù†Ûیں کر لیتے Ûیں۔"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"â€Google Play سروسز Ùعال کریں"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"â€Google Play سروسز اپ ڈیٹ کریں"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"â€Android Wear Ú©Ùˆ اپ ڈیٹ کریں"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"â€ÛŒÛ ایپ تب تک Ù†Ûیں Ú†Ù„Û’ Ú¯ÛŒ جب تک Ú©Û Ø¢Ù¾ Google Play سروسز اپ ڈیٹ Ù†Ûیں کر لیتے Ûیں۔"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"â€Ø¬Ø¨ تک آپ Android Wear ایپ Ú©Ùˆ اپ ڈیٹ Ù†Ûیں کر لیتے ÛŒÛ Ø§ÛŒÙ¾ Ù†Ûیں Ú†Ù„Û’ گی۔"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"نیٹ ورک میں خرابی"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"â€Google Play سروسز سے مربوط Ûونے کیلئے ایک ڈیٹا کنکشن Ú©ÛŒ ضرورت ÛÛ’Û”"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"غلط اکاؤنٹ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"متعین اکاؤنٹ اس Ø¢Ù„Û Ù¾Ø± موجود Ù†Ûیں ÛÛ’Û” Ø¨Ø±Ø§Û Ú©Ø±Ù… ایک مختل٠اکاؤنٹ منتخب کریں۔"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"â€Google Play سروسز Ú©Û’ ساتھ نامعلوم مسئلÛÛ”"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"â€Google Play سروسز"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"â€Google Play سروسز، جن پر آپ Ú©ÛŒ Ú©Ú†Ú¾ ایپلیکیشنز انØصار کرتی Ûیں، آپ Ú©Û’ Ø¢Ù„Û Ú©Û’ ذریعے تعاون یاÙØªÛ Ù†Ûیں ÛÛ’Û” Ø¨Ø±Ø§Û Ú©Ø±Ù… مدد کیلئے مینوÙیکچرر سے Ø±Ø§Ø¨Ø·Û Ú©Ø±ÛŒÚºÛ”"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"اپ ڈیٹ کریں"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"سائن ان کریں"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"â€Google Ú©Û’ ساتھ سائن ان کریں"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Ùون پر کھولیں"</string> +</resources> diff --git a/play-services-base/res/values-uz-rUZ/common_strings.xml b/play-services-base/res/values-uz-rUZ/common_strings.xml new file mode 100644 index 0000000..22ca05a --- /dev/null +++ b/play-services-base/res/values-uz-rUZ/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play xizmatlari xatosi"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Ilova Google Play xizmatlarining o‘rnatilishini talab qiladi."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Ilova Google Play xizmatlarining yangilanishini talab qiladi."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ilovadan foydalanish uchun Android Wear ilovasini yangilash lozim."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Ilova Google Play xizmatlarining yoqilishini talab qiladi."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"So‘rov manbasi: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Google Play xizmatlarini yuklab oling"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ushbu ilova ishlashi uchun telefoningizga Google Play xizmatlarini o‘rnatish lozim."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ushbu ilova ishlashi uchun planshetingizga Google Play xizmatlarini o‘rnatish lozim."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Google Play xizmatlarini yuklab oling"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Google Play xizmatlarini yoqish"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ushbu ilova Google Play xizmatlari yoqilmaguncha ishlamaydi."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Google Play xizmatlarini yoqish"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Google Play xizmatlarini yangilash"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Android Wear ilovasini yangilash"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ushbu ilova Google Play xizmatlari yangilanmaguncha ishlamaydi."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ushbu ilova Android Wear ilovasi yangilanmaguncha ishlamaydi."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Tarmoq xatosi"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Google Play xizmatlariga ulanish uchun internet zarur."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Hisob haqiqiy emas"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Ushbu qurilmada ko‘rsatilgan hisob mavjud emas. Boshqa hisobni tanlang."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play xizmatlari bilan bog‘liq noma’lum muammo yuz berdi."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play xizmatlari"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Ba’zi ilovalarning ishlashi uchun zarur hisoblangan Google Play xizmatlari qurilmangizda qo‘llab-quvvatlanmaydi. Yordam olish uchun ishlab chiqaruvchiga murojaat qiling."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Yangilash"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Kirish"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Google orqali kirish"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Telefonda ochish"</string> +</resources> diff --git a/play-services-base/res/values-vi/common_strings.xml b/play-services-base/res/values-vi/common_strings.xml new file mode 100644 index 0000000..24c9a82 --- /dev/null +++ b/play-services-base/res/values-vi/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Lá»—i dịch vụ của Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Má»™t ứng dụng yêu cầu cà i đặt các dịch vụ của Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Má»™t ứng dụng yêu cầu cáºp nháºt đối vá»›i các dịch vụ của Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Ứng dụng yêu cầu cáºp nháºt lên ứng dụng Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Má»™t ứng dụng yêu cầu báºt các dịch vụ của Google Play."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Äược yêu cầu bởi <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Cà i đặt dịch vụ của Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Ứng dụng nà y sẽ không chạy nếu không có dịch vụ của Google Play. Äiện thoại của bạn bị thiếu dịch vụ nà y."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Ứng dụng nà y sẽ không chạy nếu không có dịch vụ của Google Play. Máy tÃnh bảng của bạn bị thiếu dịch vụ nà y."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Cà i đặt dịch vụ của Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Báºt dịch vụ của Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Ứng dụng nà y sẽ không hoạt Ä‘á»™ng trừ khi bạn báºt dịch vụ của Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Báºt dịch vụ của Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Cáºp nháºt dịch vụ của Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Cáºp nháºt Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Ứng dụng nà y sẽ không chạy trừ khi bạn cáºp nháºt dịch vụ của Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Ứng dụng nà y chỉ chạy khi bạn cáºp nháºt ứng dụng Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Lá»—i mạng"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Cần có kết nối dữ liệu để kết nối vá»›i các dịch vụ của Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"Tà i khoản không hợp lệ"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"Tà i khoản đã chỉ định không tồn tại trên thiết bị nà y. Vui lòng chá»n má»™t tà i khoản khác."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Sá»± cố không xác định vá»›i dịch vụ của Google Play."</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Dịch vụ của Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Các dịch vụ của Google Play mà má»™t số ứng dụng của bạn dá»±a và o không được thiết bị của bạn há»— trợ. Vui lòng liên hệ vá»›i nhà sản xuất để được há»— trợ."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Cáºp nháºt"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Äăng nháºp"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Äăng nháºp bằng Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Mở trên Ä‘iện thoại"</string> +</resources> diff --git a/play-services-base/res/values-zh-rCN/common_strings.xml b/play-services-base/res/values-zh-rCN/common_strings.xml new file mode 100644 index 0000000..a886386 --- /dev/null +++ b/play-services-base/res/values-zh-rCN/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google PlayæœåŠ¡å‡ºé”™"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"安装Google PlayæœåŠ¡åŽæ‰èƒ½è¿è¡Œåº”用。"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"æ›´æ–°Google PlayæœåŠ¡åŽæ‰èƒ½è¿è¡Œåº”用。"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"æŸä¸ªåº”用需è¦æ›´æ–°Android Wear应用æ‰èƒ½æ£å¸¸è¿è¡Œã€‚"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"å¯ç”¨Google PlayæœåŠ¡åŽæ‰èƒ½è¿è¡Œåº”用。"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"<xliff:g id="APP_NAME">%1$s</xliff:g>å‘出的请求"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"获å–Google PlayæœåŠ¡"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"您的手机ä¸æ²¡æœ‰Google PlayæœåŠ¡ï¼Œæ‚¨å¿…须先安装该æœåŠ¡æ‰èƒ½è¿è¡Œæ¤åº”用。"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"您的平æ¿ç”µè„‘ä¸æ²¡æœ‰Google PlayæœåŠ¡ï¼Œæ‚¨å¿…须先安装该æœåŠ¡æ‰èƒ½è¿è¡Œæ¤åº”用。"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"获å–Google PlayæœåŠ¡"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"å¯ç”¨Google PlayæœåŠ¡"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"您必须先å¯ç”¨Google PlayæœåŠ¡æ‰èƒ½è¿è¡Œæ¤åº”用。"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"å¯ç”¨Google PlayæœåŠ¡"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"æ›´æ–°Google PlayæœåŠ¡"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"æ›´æ–°Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"您必须先更新Google PlayæœåŠ¡æ‰èƒ½è¿è¡Œæ¤åº”用。"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"åªæœ‰æ›´æ–°Android Wear应用åŽï¼Œæ¤åº”用æ‰èƒ½æ£å¸¸è¿è¡Œã€‚"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"网络错误"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"您必须有数æ®ç½‘络连接æ‰èƒ½æŽ¥å…¥Google PlayæœåŠ¡ã€‚"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"æ— æ•ˆå¸æˆ·"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"æ¤è®¾å¤‡ä¸Šä¸å˜åœ¨æŒ‡å®šçš„å¸æˆ·ï¼Œè¯·é€‰æ‹©å…¶ä»–å¸æˆ·ã€‚"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google PlayæœåŠ¡å‡ºçŽ°æœªçŸ¥é—®é¢˜ã€‚"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google PlayæœåŠ¡"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"您的设备ä¸æ”¯æŒéƒ¨åˆ†åº”用所ä¾èµ–çš„Google PlayæœåŠ¡ã€‚è¯·ä¸Žè®¾å¤‡åˆ¶é€ å•†è”系,以寻求帮助。"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"æ›´æ–°"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"登录"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"使用Googleå¸æˆ·ç™»å½•"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"在手机上打开"</string> +</resources> diff --git a/play-services-base/res/values-zh-rHK/common_strings.xml b/play-services-base/res/values-zh-rHK/common_strings.xml new file mode 100644 index 0000000..3cf8121 --- /dev/null +++ b/play-services-base/res/values-zh-rHK/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play æœå‹™éŒ¯èª¤"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"å¿…é ˆå®‰è£ã€ŒGoogle Play æœå‹™ã€ï¼Œæ‰èƒ½ä½¿ç”¨æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"å¿…é ˆæ›´æ–°ã€ŒGoogle Play æœå‹™ã€ï¼Œæ‰èƒ½ä½¿ç”¨æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"有一個應用程å¼è¦æ±‚æ›´æ–° Android Wear 應用程å¼ã€‚"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"å¿…é ˆå•Ÿç”¨ã€ŒGoogle Play æœå‹™ã€ï¼Œæ‰èƒ½ä½¿ç”¨æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"「<xliff:g id="APP_NAME">%1$s</xliff:g>ã€æ出è¦æ±‚"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"å–å¾— Google Play æœå‹™"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"æ‚¨çš„æ‰‹æ©Ÿæœªå®‰è£ Google Play æœå‹™ï¼Œå®‰è£å¾Œæ‰èƒ½åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"您的平æ¿é›»è…¦æœªå®‰è£ Google Play æœå‹™ï¼Œå®‰è£å¾Œæ‰èƒ½åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"å–å¾— Google Play æœå‹™"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"啟用 Google Play æœå‹™"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"æ‚¨å¿…é ˆå•Ÿç”¨ Google Play æœå‹™ï¼Œæ‰èƒ½åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"啟用 Google Play æœå‹™"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"æ›´æ–° Google Play æœå‹™"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"æ›´æ–° Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"æ‚¨å¿…é ˆæ›´æ–° Google Play æœå‹™ï¼Œæ‰èƒ½åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"æ‚¨å¿…é ˆæ›´æ–° Android Wear 應用程å¼ï¼Œé€™å€‹æ‡‰ç”¨ç¨‹å¼æ‰èƒ½é‹ä½œã€‚"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"網絡錯誤"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"è¦é€£æŽ¥ Google Play æœå‹™ï¼Œå¿…需數據連線。"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"無效的帳戶"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"這個è£ç½®ä¸Šæ²’有您指定的帳戶,請é¸æ“‡å…¶ä»–帳戶。"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play æœå‹™å‡ºç¾ä¸æ˜Žå•é¡Œã€‚"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play æœå‹™"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"您的è£ç½®ä¸æ”¯æ´éƒ¨åˆ†æ‡‰ç”¨ç¨‹å¼æ‰€éœ€çš„ Google Play æœå‹™ã€‚如需å”助,請與您的è£ç½®è£½é€ 商è¯çµ¡ã€‚"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"æ›´æ–°"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"登入"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"登入 Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"在手機ä¸é–‹å•Ÿ"</string> +</resources> diff --git a/play-services-base/res/values-zh-rTW/common_strings.xml b/play-services-base/res/values-zh-rTW/common_strings.xml new file mode 100644 index 0000000..c443f7c --- /dev/null +++ b/play-services-base/res/values-zh-rTW/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Google Play æœå‹™ç™¼ç”ŸéŒ¯èª¤"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"應用程å¼è¦æ±‚å®‰è£ Google Play æœå‹™ã€‚"</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"應用程å¼è¦æ±‚æ›´æ–° Google Play æœå‹™ã€‚"</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"有一個應用程å¼è¦æ±‚æ›´æ–° Android Wear 應用程å¼ã€‚"</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"應用程å¼è¦æ±‚啟用 Google Play æœå‹™ã€‚"</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"「<xliff:g id="APP_NAME">%1$s</xliff:g>ã€æ出è¦æ±‚"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"å–å¾— Google Play æœå‹™"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"æ‚¨çš„æ‰‹æ©Ÿä¸¦æœªå®‰è£ Google Play æœå‹™ï¼Œæ‰€ä»¥ç„¡æ³•åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"您的平æ¿é›»è…¦ä¸¦æœªå®‰è£ Google Play æœå‹™ï¼Œæ‰€ä»¥ç„¡æ³•åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"å–å¾— Google Play æœå‹™"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"啟用 Google Play æœå‹™"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"æ‚¨å¿…é ˆå•Ÿç”¨ Google Play æœå‹™ï¼Œé€™å€‹æ‡‰ç”¨ç¨‹å¼æ‰èƒ½é‹ä½œã€‚"</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"啟用 Google Play æœå‹™"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"æ›´æ–° Google Play æœå‹™"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"æ›´æ–° Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"æ‚¨å¿…é ˆæ›´æ–° Google Play æœå‹™ï¼Œæ‰èƒ½åŸ·è¡Œé€™å€‹æ‡‰ç”¨ç¨‹å¼ã€‚"</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"æ‚¨å¿…é ˆæ›´æ–° Android Wear 應用程å¼ï¼Œé€™å€‹æ‡‰ç”¨ç¨‹å¼æ‰èƒ½é‹ä½œã€‚"</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"網路錯誤"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"需è¦æ•¸æ“šé€£ç·šæ‰èƒ½é€£ä¸Š Google Play æœå‹™ã€‚"</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"無效的帳戶"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"這個è£ç½®ä¸Šæ²’有您所指定的帳戶,請é¸æ“‡å…¶ä»–帳戶。"</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Google Play æœå‹™ç™¼ç”Ÿä¸æ˜Žå•é¡Œã€‚"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Google Play æœå‹™"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"您的è£ç½®ä¸æ”¯æ´éƒ¨åˆ†æ‡‰ç”¨ç¨‹å¼æ‰€éœ€çš„ Google Play æœå‹™ã€‚如需å”助,請與您的è£ç½®è£½é€ 商è¯çµ¡ã€‚"</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"æ›´æ–°"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"登入"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"使用 Google 帳戶登入"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"在手機上開啟"</string> +</resources> diff --git a/play-services-base/res/values-zu/common_strings.xml b/play-services-base/res/values-zu/common_strings.xml new file mode 100644 index 0000000..82fe012 --- /dev/null +++ b/play-services-base/res/values-zu/common_strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="common_google_play_services_notification_ticker" msgid="1852570676146674985">"Iphutha lamasevisi we-Google Play"</string> + <string name="common_google_play_services_notification_needs_installation_title" msgid="8120534356798772974">"Uhlelo lokusebenza ludinga ukufakwa kwamasevisi we-Google Play."</string> + <string name="common_google_play_services_notification_needs_update_title" msgid="1388129345631079938">"Uhlelo lokusebenza ludinga isibuyekezo samasevisi we-Google Play."</string> + <string name="common_android_wear_notification_needs_update_text" msgid="473679118463211576">"Uhlelo lokusebenza ludinga ukubuyekezelwa kuhlelo lokusebenza le-Android Wear."</string> + <string name="common_google_play_services_needs_enabling_title" msgid="2583358409598976717">"Uhlelo lokusebenza ludinga amasevisi we-Google Play ukuze anikwe amandla."</string> + <string name="common_google_play_services_error_notification_requested_by_msg" msgid="2443362625939284971">"Icelwe yi-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="common_google_play_services_install_title" msgid="26645092511305524">"Thola amasevisi e-Google Play"</string> + <string name="common_google_play_services_install_text_phone" msgid="8685301130651051380">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho efonini yakho."</string> + <string name="common_google_play_services_install_text_tablet" msgid="1589957570365247855">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho kuthebulethi yakho."</string> + <string name="common_google_play_services_install_button" msgid="8515591849428043265">"Thola amasevisi e-Google Play"</string> + <string name="common_google_play_services_enable_title" msgid="529078775174559253">"Nika amandla amasevisi e-Google Play"</string> + <string name="common_google_play_services_enable_text" msgid="7627896071867667758">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi unike amandla amasevisi e-Google Play."</string> + <string name="common_google_play_services_enable_button" msgid="4181637455539816337">"Nika amandla amasevisi e-Google Play"</string> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">"Buyekeza amasevisi e-Google Play"</string> + <string name="common_android_wear_update_title" msgid="1366439133145190222">"Buyekeza i-Android Wear"</string> + <string name="common_google_play_services_update_text" msgid="448354684997260580">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi ubuyekeze amasevisi e-Google Play."</string> + <string name="common_android_wear_update_text" msgid="3046420540094071256">"Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kokuthi ubuyekeze uhlelo lokusebenza le-Android Wear."</string> + <string name="common_google_play_services_network_error_title" msgid="3827284619958211114">"Iphutha lenethiwekhi"</string> + <string name="common_google_play_services_network_error_text" msgid="9038847255613537209">"Kudingeka ukuxhumeka kwedatha ukuze kuxhunyekwe kumasevisi we-Google Play."</string> + <string name="common_google_play_services_invalid_account_title" msgid="1066672360770936753">"I-Akhawunti engavumelekile"</string> + <string name="common_google_play_services_invalid_account_text" msgid="4983316348021735578">"I-Akhawunti ecacisiwe ayikho kule divayisi. Sicela ukhethe i-akhawunti ehlukile."</string> + <string name="common_google_play_services_unknown_issue" msgid="4762332809710093730">"Indaba engaziwa yamasevisi we-Google Play"</string> + <string name="common_google_play_services_unsupported_title" msgid="6334768798839376943">"Amasevisi we-Google Play"</string> + <string name="common_google_play_services_unsupported_text" msgid="3542578567569488671">"Amasevisi we-Google Play, okungukuthi ezinye izinhlelo zakho zithembele kuwo, awasekelwe yidivayisi yakho. Sicela uxhumane nomkhiqizi ukuze uthole usizo."</string> + <string name="common_google_play_services_update_button" msgid="8932944190611227642">"Isibuyekezo"</string> + <string name="common_signin_button_text" msgid="9071884888741449141">"Ngena ngemvume"</string> + <string name="common_signin_button_text_long" msgid="2429381841831957106">"Ngena ngemvume nge-Google"</string> + <string name="common_open_on_phone" msgid="411506735369601515">"Vula kufoni"</string> +</resources> diff --git a/play-services-base/res/values/common_attrs.xml b/play-services-base/res/values/common_attrs.xml new file mode 100644 index 0000000..8740250 --- /dev/null +++ b/play-services-base/res/values/common_attrs.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- Copyright 2014 Google Inc. All Rights Reserved. --> +<resources> + + <!-- Attributes for LoadingImageView --> + <declare-styleable name="LoadingImageView"> + + <!-- + What kind of aspect ratio adjustment to do. It must be one of "none", "adjust_width", + or "adjust_height". + --> + <attr name="imageAspectRatioAdjust" format="enum"> + <enum name="none" value="0" /> + <enum name="adjust_width" value="1" /> + <enum name="adjust_height" value="2" /> + </attr> + + <!-- + The fixed aspect ratio to use in aspect ratio adjustments. + --> + <attr name="imageAspectRatio" format="float" /> + + <!-- + Whether or not this view should have a circular clip applied + --> + <attr name="circleCrop" format="boolean" /> + + </declare-styleable> + +</resources> diff --git a/play-services-base/res/values/common_colors.xml b/play-services-base/res/values/common_colors.xml new file mode 100644 index 0000000..6b2740a --- /dev/null +++ b/play-services-base/res/values/common_colors.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources> + <!-- Sign-in Button Colors --> + <color name="common_signin_btn_dark_text_default">@android:color/white</color> + <color name="common_signin_btn_dark_text_pressed">@android:color/white</color> + <color name="common_signin_btn_dark_text_disabled">#FFAAAAAA</color> + <color name="common_signin_btn_dark_text_focused">@android:color/white</color> + <color name="common_signin_btn_light_text_default">#FF737373</color> + <color name="common_signin_btn_light_text_pressed">@android:color/white</color> + <color name="common_signin_btn_light_text_disabled">#FFAAAAAA</color> + <color name="common_signin_btn_light_text_focused">#FF737373</color> + <color name="common_signin_btn_default_background">#FFDD4B39</color> + <color name="common_action_bar_splitter">#d2d2d2</color> +</resources>
\ No newline at end of file diff --git a/play-services-base/res/values/common_strings.xml b/play-services-base/res/values/common_strings.xml new file mode 100644 index 0000000..24558ac --- /dev/null +++ b/play-services-base/res/values/common_strings.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Title for notification shown when GooglePlayServices is unavailable [CHAR LIMIT=42] --> + <string name="common_google_play_services_notification_ticker">Google Play services error</string> + <!-- Title for notification shown when GooglePlayServices needs to be installed + for an application to work. [CHAR LIMIT=70] --> + <string name="common_google_play_services_notification_needs_installation_title">An application requires installation of Google Play services.</string> + <!-- Title for notification shown when GooglePlayServices needs to be updated for an + application to work. [CHAR LIMIT=70] --> + <string name="common_google_play_services_notification_needs_update_title">An application requires an update for Google Play services.</string> + <!-- Text for notification shown when the Android Wear apps needs to be updated. Only shown on the wearable. [CHAR LIMIT=NONE] --> + <string name="common_android_wear_notification_needs_update_text">An application requires an update to the Android Wear app.</string> + <!-- Title for notification shown when GooglePlayServices needs to be enabled for an + application to work. [CHAR LIMIT=70] --> + <string name="common_google_play_services_needs_enabling_title">An application requires Google Play services to be enabled.</string> + + <!-- Requested by string saying which app requested the notification. [CHAR LIMIT=42] --> + <string name="common_google_play_services_error_notification_requested_by_msg">Requested by <xliff:g id="app_name">%1$s</xliff:g></string> + + <!-- Title of confirmation dialog informing user that they need to install + Google Play services (from Play Store) [CHAR LIMIT=40] --> + <string name="common_google_play_services_install_title" msgid="7215213145546190223">Get Google Play services</string> + + <!-- (For phones) Message in confirmation dialog informing user that + they need to install Google Play services (from Play Store) [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_install_text_phone" msgid="2122112764540849864">This app won\'t run without Google Play services, which are missing from your phone.</string> + + <!-- (For tablets) Message in confirmation dialog informing user that + they need to install Google Play services (from Play Store) [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_install_text_tablet" msgid="7351599665250191022">This app won\'t run without Google Play services, which are missing from your tablet.</string> + + <!-- Button in confirmation dialog for installing Google Play services [CHAR LIMIT=40] --> + <string name="common_google_play_services_install_button" msgid="7153882981874058840">Get Google Play services</string> + + <!-- Title of confirmation dialog informing user they need to enable + Google Play services in application settings [CHAR LIMIT=40] --> + <string name="common_google_play_services_enable_title" msgid="5122002158466380389">Enable Google Play services</string> + + <!-- Message in confirmation dialog informing user they need to enable + Google Play services in application settings [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_enable_text" msgid="227660514972886228">This app won\'t work unless you enable Google Play services.</string> + + <!-- Button in confirmation dialog to enable Google Play services. Clicking it + will direct user to application settings of Google Play services where they + can enable it [CHAR LIMIT=40] --> + <string name="common_google_play_services_enable_button" msgid="2523291102206661146">Enable Google Play services</string> + + <!-- Title of confirmation dialog informing user that they need to update + Google Play services (from Play Store) [CHAR LIMIT=40] --> + <string name="common_google_play_services_update_title" msgid="6006316683626838685">Update Google Play services</string> + + <!-- Title of confirmation dialog informing user that they need to update + the Android Wear app (from Play Store) [CHAR LIMIT=40] --> + <string name="common_android_wear_update_title" msgid="6006316683626838685">Update Android Wear</string> + + <!-- Message in confirmation dialog informing user that they need to update + Google Play services (from Play Store) [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_update_text" msgid="9053896323427875356">This app won\'t run unless you update Google Play services.</string> + + <!-- Message in confirmation dialog informing user that they need to update + the Android Wear app [CHAR LIMIT=NONE] --> + <string name="common_android_wear_update_text">This app won\'t run unless you update the Android Wear app.</string> + + <!-- Title of confirmation dialog informing the user that a network error occurred. [CHAR LIMIT=40] --> + <string name="common_google_play_services_network_error_title">Network Error</string> + + <!-- Message in confirmation dialog informing the user that a network error occurred. [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_network_error_text">A data connection is required to connect to Google Play services.</string> + + <!-- Title of confirmation dialog informing the user that they provided an invalid account. [CHAR LIMIT=40] --> + <string name="common_google_play_services_invalid_account_title">Invalid Account</string> + + <!-- Message in confirmation dialog informing the user that they provided an invalid account. [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_invalid_account_text">The specified account does not exist on this device. Please choose a different account.</string> + + <!-- Message in confirmation dialog informing user there is an unknown issue in Google Play + services [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_unknown_issue">Unknown issue with Google Play services.</string> + + <!-- Title of confirmation dialog informing user that Google Play services is not supported on their device [CHAR LIMIT=40] --> + <string name="common_google_play_services_unsupported_title">Google Play services</string> + + <!-- Message in confirmation dialog informing user that Google Play services is not supported on their device [CHAR LIMIT=NONE] --> + <string name="common_google_play_services_unsupported_text">Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance.</string> + + <!-- Button in confirmation dialog for updating Google Play services [CHAR LIMIT=40] --> + <string name="common_google_play_services_update_button" msgid="6556509956452265614">Update</string> + + <!-- Sign-in button text [CHAR LIMIT=15] --> + <string name="common_signin_button_text">Sign in</string> + + <!-- Long form sign-in button text [CHAR LIMIT=30] --> + <string name="common_signin_button_text_long">Sign in with Google</string> + + <!-- Label for an action to open a notifications content on the phone [CHAR LIMIT=25] --> + <string name="common_open_on_phone">Open on phone</string> + +</resources> diff --git a/play-services-base/res/values/version.xml b/play-services-base/res/values/version.xml new file mode 100644 index 0000000..d9cb5ea --- /dev/null +++ b/play-services-base/res/values/version.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <integer name="google_play_services_version">6587000</integer> +</resources>
\ No newline at end of file diff --git a/play-services-base/src/.gitkeep b/play-services-base/src/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/play-services-base/src/.gitkeep diff --git a/play-services-location/.classpath b/play-services-location/.classpath new file mode 100644 index 0000000..f8b9238 --- /dev/null +++ b/play-services-location/.classpath @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"> + <attributes> + <attribute name="ignore_optional_problems" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="src" path="gen"> + <attributes> + <attribute name="ignore_optional_problems" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/play-services-location/.project b/play-services-location/.project new file mode 100644 index 0000000..14e2859 --- /dev/null +++ b/play-services-location/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>play-services-location</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/play-services-location/.settings/org.eclipse.jdt.core.prefs b/play-services-location/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b080d2d --- /dev/null +++ b/play-services-location/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/play-services-location/AndroidManifest.xml b/play-services-location/AndroidManifest.xml new file mode 100644 index 0000000..c3729c9 --- /dev/null +++ b/play-services-location/AndroidManifest.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.android.gms.location"> + <uses-sdk android:minSdkVersion="9"/> + <application /> +</manifest> diff --git a/play-services-location/build.xml b/play-services-location/build.xml new file mode 100644 index 0000000..157ab53 --- /dev/null +++ b/play-services-location/build.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="play_services_location" default="help"> + + <!-- The local.properties file is created and updated by the 'android' tool. + It contains the path to the SDK. It should *NOT* be checked into + Version Control Systems. --> + <property file="local.properties" /> + + <!-- The ant.properties file can be created by you. It is only edited by the + 'android' tool to add properties to it. + This is the place to change some Ant specific build properties. + Here are some properties you may want to change/update: + + source.dir + The name of the source directory. Default is 'src'. + out.dir + The name of the output directory. Default is 'bin'. + + For other overridable properties, look at the beginning of the rules + files in the SDK, at tools/ant/build.xml + + Properties related to the SDK location or the project target should + be updated using the 'android' tool with the 'update' action. + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. + + --> + <property file="ant.properties" /> + + <!-- if sdk.dir was not set from one of the property file, then + get it from the ANDROID_HOME env var. + This must be done before we load project.properties since + the proguard config can use sdk.dir --> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + + <!-- The project.properties file is created and updated by the 'android' + tool, as well as ADT. + + This contains project specific properties such as project target, and library + dependencies. Lower level build properties are stored in ant.properties + (or in .classpath for Eclipse projects). + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> + <loadproperties srcFile="project.properties" /> + + <!-- quick check on sdk.dir --> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." + unless="sdk.dir" /> + + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> + + <!-- Import the actual build file. + + To customize existing targets, there are two options: + - Customize only one target: + - copy/paste the target into this file, *before* the + <import> task. + - customize it to your needs. + - Customize the whole content of build.xml + - copy/paste the content of the rules files (minus the top node) + into this file, replacing the <import> task. + - customize to your needs. + + *********************** + ****** IMPORTANT ****** + *********************** + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, + in order to avoid having your file be overridden by tools such as "android update project" + --> + <!-- version-tag: 1 --> + <import file="${sdk.dir}/tools/ant/build.xml" /> + +</project> diff --git a/play-services-location/libs/play-services-location.jar b/play-services-location/libs/play-services-location.jar Binary files differnew file mode 100644 index 0000000..b440785 --- /dev/null +++ b/play-services-location/libs/play-services-location.jar diff --git a/play-services-location/lint.xml b/play-services-location/lint.xml new file mode 100644 index 0000000..715caf3 --- /dev/null +++ b/play-services-location/lint.xml @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> + <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> + <issue id="AllowBackup" severity="ignore" /> + <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> + <issue id="ButtonCase" severity="ignore" /> + <issue id="ButtonOrder" severity="ignore" /> + <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> + <issue id="CommitPrefEdits" severity="ignore" /> + <issue id="CommitTransaction" severity="ignore" /> + <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> + <issue id="CutPasteId" severity="ignore" /> + <issue id="DalvikOverride" severity="ignore" /> + <issue id="DefaultLocale" severity="ignore" /> + <issue id="Deprecated" severity="ignore" /> + <issue id="DeviceAdmin" severity="ignore" /> + <issue id="DisableBaselineAlignment" severity="ignore" /> + <issue id="DrawAllocation" severity="ignore" /> + <issue id="DuplicateActivity" severity="ignore" /> + <issue id="DuplicateDefinition" severity="ignore" /> + <issue id="DuplicateIds" severity="ignore" /> + <issue id="DuplicateIncludedIds" severity="ignore" /> + <issue id="DuplicateUsesFeature" severity="ignore" /> + <issue id="EnforceUTF8" severity="ignore" /> + <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> + <issue id="ExportedReceiver" severity="ignore" /> + <issue id="ExportedService" severity="ignore" /> + <issue id="ExtraText" severity="ignore" /> + <issue id="ExtraTranslation" severity="ignore" /> + <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> + <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> + <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> + <issue id="GrantAllUris" severity="ignore" /> + <issue id="GridLayout" severity="ignore" /> + <issue id="HandlerLeak" severity="ignore" /> + <issue id="HardcodedDebugMode" severity="ignore" /> + <issue id="HardcodedText" severity="ignore" /> + <issue id="IconColors" severity="ignore" /> + <issue id="IconDensities" severity="ignore" /> + <issue id="IconDipSize" severity="ignore" /> + <issue id="IconDuplicates" severity="ignore" /> + <issue id="IconDuplicatesConfig" severity="ignore" /> + <issue id="IconExtension" severity="ignore" /> + <issue id="IconLauncherShape" severity="ignore" /> + <issue id="IconLocation" severity="ignore" /> + <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="IconMixedNinePatch" severity="ignore" /> + <issue id="IconNoDpi" severity="ignore" /> + <issue id="IconXmlAndPng" severity="ignore" /> + <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> + <issue id="InconsistentArrays" severity="ignore" /> + <issue id="InconsistentLayout" severity="ignore" /> + <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> + <issue id="InlinedApi" severity="ignore" /> + <issue id="InnerclassSeparator" severity="ignore" /> + <issue id="Instantiatable" severity="ignore" /> + <issue id="InvalidId" severity="ignore" /> + <issue id="InvalidPackage" severity="ignore" /> + <issue id="JavascriptInterface" severity="ignore" /> + <issue id="LabelFor" severity="ignore" /> + <issue id="LibraryCustomView" severity="ignore" /> + <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> + <issue id="MangledCRLF" severity="ignore" /> + <issue id="ManifestOrder" severity="ignore" /> + <issue id="ManifestTypo" severity="ignore" /> + <issue id="MenuTitle" severity="ignore" /> + <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MissingApplicationIcon" severity="ignore" /> + <issue id="MissingId" severity="ignore" /> + <issue id="MissingPrefix" severity="ignore" /> + <issue id="MissingQuantity" severity="ignore" /> + <issue id="MissingRegistered" severity="ignore" /> + <issue id="MissingSuperCall" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> + <issue id="MissingVersion" severity="ignore" /> + <issue id="MockLocation" severity="ignore" /> + <issue id="MultipleUsesSdk" severity="ignore" /> + <issue id="NamespaceTypo" severity="ignore" /> + <issue id="NestedScrolling" severity="ignore" /> + <issue id="NestedWeights" severity="ignore" /> + <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> + <issue id="NotSibling" severity="ignore" /> + <issue id="ObsoleteLayoutParam" severity="ignore" /> + <issue id="OldTargetApi" severity="ignore" /> + <issue id="OnClick" severity="ignore" /> + <issue id="Orientation" severity="ignore" /> + <issue id="Overdraw" severity="ignore" /> + <issue id="Override" severity="ignore" /> + <issue id="PackagedPrivateKey" severity="ignore" /> + <issue id="ParcelCreator" severity="ignore" /> + <issue id="PrivateResource" severity="ignore" /> + <issue id="Proguard" severity="ignore" /> + <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> + <issue id="ProtectedPermissions" severity="ignore" /> + <issue id="PxUsage" severity="ignore" /> + <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> + <issue id="Registered" severity="ignore" /> + <issue id="RequiredSize" severity="ignore" /> + <issue id="ResAuto" severity="ignore" /> + <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> + <issue id="ScrollViewCount" severity="ignore" /> + <issue id="ScrollViewSize" severity="ignore" /> + <issue id="SdCardPath" severity="ignore" /> + <issue id="SecureRandom" severity="ignore" /> + <issue id="ServiceCast" severity="ignore" /> + <issue id="SetJavaScriptEnabled" severity="ignore" /> + <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> + <issue id="SimpleDateFormat" severity="ignore" /> + <issue id="SmallSp" severity="ignore" /> + <issue id="SpUsage" severity="ignore" /> + <issue id="StateListReachable" severity="ignore" /> + <issue id="StringFormatCount" severity="ignore" /> + <issue id="StringFormatInvalid" severity="ignore" /> + <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> + <issue id="Suspicious0dp" severity="ignore" /> + <issue id="SuspiciousImport" severity="ignore" /> + <issue id="TextFields" severity="ignore" /> + <issue id="TextViewEdits" severity="ignore" /> + <issue id="TooDeepLayout" severity="ignore" /> + <issue id="TooManyViews" severity="ignore" /> + <issue id="TrulyRandom" severity="ignore" /> + <issue id="TypographyDashes" severity="ignore" /> + <issue id="TypographyEllipsis" severity="ignore" /> + <issue id="TypographyFractions" severity="ignore" /> + <issue id="TypographyOther" severity="ignore" /> + <issue id="Typos" severity="ignore" /> + <issue id="UniquePermission" severity="ignore" /> + <issue id="UnknownId" severity="ignore" /> + <issue id="UnknownIdInLayout" severity="ignore" /> + <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> + <issue id="UnusedNamespace" severity="ignore" /> + <issue id="UnusedQuantity" severity="ignore" /> + <issue id="UnusedResources" severity="ignore" /> + <issue id="UseCheckPermission" severity="ignore" /> + <issue id="UseCompoundDrawables" severity="ignore" /> + <issue id="UseSparseArrays" severity="ignore" /> + <issue id="UseValueOf" severity="ignore" /> + <issue id="UselessLeaf" severity="ignore" /> + <issue id="UselessParent" severity="ignore" /> + <issue id="UsesMinSdkAttributes" severity="ignore" /> + <issue id="ValidFragment" severity="ignore" /> + <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> + <issue id="ViewTag" severity="ignore" /> + <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> + <issue id="WorldReadableFiles" severity="ignore" /> + <issue id="WorldWriteableFiles" severity="ignore" /> + <issue id="WrongCall" severity="ignore" /> + <issue id="WrongCase" severity="ignore" /> + <issue id="WrongFolder" severity="ignore" /> + <issue id="WrongManifestParent" severity="ignore" /> + <issue id="WrongViewCast" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/play-services-location/play-services-location.iml b/play-services-location/play-services-location.iml new file mode 100644 index 0000000..3525dde --- /dev/null +++ b/play-services-location/play-services-location.iml @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="android" name="Android"> + <configuration> + <option name="LIBRARY_PROJECT" value="true" /> + <option name="UPDATE_PROPERTY_FILES" value="false" /> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module-library" exported=""> + <library> + <CLASSES> + <root url="file://$MODULE_DIR$/libs" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + <jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" /> + </library> + </orderEntry> + </component> + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/play-services-location/proguard.txt b/play-services-location/proguard.txt new file mode 100644 index 0000000..199d972 --- /dev/null +++ b/play-services-location/proguard.txt @@ -0,0 +1,23 @@ +-keep class * extends java.util.ListResourceBundle { + protected Object[][] getContents(); +} + +# Keep SafeParcelable value, needed for reflection. This is required to support backwards +# compatibility of some classes. +-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { + public static final *** NULL; +} + +# Keep the names of classes/members we need for client functionality. +-keepnames @com.google.android.gms.common.annotation.KeepName class * +-keepclassmembernames class * { + @com.google.android.gms.common.annotation.KeepName *; +} + +# Needed for Parcelable/SafeParcelable Creators to not get stripped +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; +} + +-dontwarn com.google.android.gms.common.** +-dontwarn com.google.android.gms.internal.**
\ No newline at end of file diff --git a/play-services-location/project.properties b/play-services-location/project.properties new file mode 100644 index 0000000..51a7632 --- /dev/null +++ b/play-services-location/project.properties @@ -0,0 +1,16 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.txt + +# Project target. +target=Google Inc.:Google APIs:21 +android.library=true +android.library.reference.1=../play-services-base diff --git a/play-services-location/res/drawable-hdpi/powered_by_google_dark.png b/play-services-location/res/drawable-hdpi/powered_by_google_dark.png Binary files differnew file mode 100644 index 0000000..721905c --- /dev/null +++ b/play-services-location/res/drawable-hdpi/powered_by_google_dark.png diff --git a/play-services-location/res/drawable-hdpi/powered_by_google_light.png b/play-services-location/res/drawable-hdpi/powered_by_google_light.png Binary files differnew file mode 100644 index 0000000..53328af --- /dev/null +++ b/play-services-location/res/drawable-hdpi/powered_by_google_light.png diff --git a/play-services-location/res/drawable-mdpi/powered_by_google_dark.png b/play-services-location/res/drawable-mdpi/powered_by_google_dark.png Binary files differnew file mode 100644 index 0000000..a152807 --- /dev/null +++ b/play-services-location/res/drawable-mdpi/powered_by_google_dark.png diff --git a/play-services-location/res/drawable-mdpi/powered_by_google_light.png b/play-services-location/res/drawable-mdpi/powered_by_google_light.png Binary files differnew file mode 100644 index 0000000..015a0ad --- /dev/null +++ b/play-services-location/res/drawable-mdpi/powered_by_google_light.png diff --git a/play-services-location/res/drawable-xhdpi/powered_by_google_dark.png b/play-services-location/res/drawable-xhdpi/powered_by_google_dark.png Binary files differnew file mode 100644 index 0000000..ffd9126 --- /dev/null +++ b/play-services-location/res/drawable-xhdpi/powered_by_google_dark.png diff --git a/play-services-location/res/drawable-xhdpi/powered_by_google_light.png b/play-services-location/res/drawable-xhdpi/powered_by_google_light.png Binary files differnew file mode 100644 index 0000000..d9f0593 --- /dev/null +++ b/play-services-location/res/drawable-xhdpi/powered_by_google_light.png diff --git a/play-services-location/res/drawable-xxhdpi/powered_by_google_dark.png b/play-services-location/res/drawable-xxhdpi/powered_by_google_dark.png Binary files differnew file mode 100644 index 0000000..0165a01 --- /dev/null +++ b/play-services-location/res/drawable-xxhdpi/powered_by_google_dark.png diff --git a/play-services-location/res/drawable-xxhdpi/powered_by_google_light.png b/play-services-location/res/drawable-xxhdpi/powered_by_google_light.png Binary files differnew file mode 100644 index 0000000..aa6b6db --- /dev/null +++ b/play-services-location/res/drawable-xxhdpi/powered_by_google_light.png diff --git a/play-services-location/src/.gitkeep b/play-services-location/src/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/play-services-location/src/.gitkeep diff --git a/showcaseview/.settings/org.eclipse.jdt.core.prefs b/showcaseview/.settings/org.eclipse.jdt.core.prefs index b080d2d..caa7ac8 100644 --- a/showcaseview/.settings/org.eclipse.jdt.core.prefs +++ b/showcaseview/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,100 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.6 diff --git a/showcaseview/build.gradle b/showcaseview/build.gradle index 0ebebe4..e5b0945 100644 --- a/showcaseview/build.gradle +++ b/showcaseview/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'android-library' android { compileSdkVersion 19 - buildToolsVersion "20" + buildToolsVersion "21.1.2" sourceSets { main { diff --git a/showcaseview/lint.xml b/showcaseview/lint.xml new file mode 100644 index 0000000..1ff0c2f --- /dev/null +++ b/showcaseview/lint.xml @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> + <issue id="AaptCrash" severity="ignore" /> + <issue id="AccidentalOctal" severity="ignore" /> + <issue id="AdapterViewChildren" severity="ignore" /> + <issue id="AddJavascriptInterface" severity="ignore" /> + <issue id="AllowBackup" severity="ignore" /> + <issue id="AlwaysShowAction" severity="ignore" /> + <issue id="AndroidGradlePluginVersion" severity="ignore" /> + <issue id="AppCompatMethod" severity="ignore" /> + <issue id="AppCompatResource" severity="ignore" /> + <issue id="Assert" severity="ignore" /> + <issue id="ButtonCase" severity="ignore" /> + <issue id="ButtonOrder" severity="ignore" /> + <issue id="ButtonStyle" severity="ignore" /> + <issue id="ByteOrderMark" severity="ignore" /> + <issue id="ClickableViewAccessibility" severity="ignore" /> + <issue id="CommitPrefEdits" severity="ignore" /> + <issue id="CommitTransaction" severity="ignore" /> + <issue id="ContentDescription" severity="ignore" /> + <issue id="CustomViewStyleable" severity="ignore" /> + <issue id="CutPasteId" severity="ignore" /> + <issue id="DalvikOverride" severity="ignore" /> + <issue id="DefaultLocale" severity="ignore" /> + <issue id="Deprecated" severity="ignore" /> + <issue id="DeviceAdmin" severity="ignore" /> + <issue id="DisableBaselineAlignment" severity="ignore" /> + <issue id="DrawAllocation" severity="ignore" /> + <issue id="DuplicateActivity" severity="ignore" /> + <issue id="DuplicateDefinition" severity="ignore" /> + <issue id="DuplicateIds" severity="ignore" /> + <issue id="DuplicateIncludedIds" severity="ignore" /> + <issue id="DuplicateUsesFeature" severity="ignore" /> + <issue id="EnforceUTF8" severity="ignore" /> + <issue id="ExportedContentProvider" severity="ignore" /> + <issue id="ExportedPreferenceActivity" severity="ignore" /> + <issue id="ExportedReceiver" severity="ignore" /> + <issue id="ExportedService" severity="ignore" /> + <issue id="ExtraText" severity="ignore" /> + <issue id="ExtraTranslation" severity="ignore" /> + <issue id="FloatMath" severity="ignore" /> + <issue id="GetInstance" severity="ignore" /> + <issue id="GifUsage" severity="ignore" /> + <issue id="GradleCompatible" severity="ignore" /> + <issue id="GradleDependency" severity="ignore" /> + <issue id="GradleDeprecated" severity="ignore" /> + <issue id="GradleDynamicVersion" severity="ignore" /> + <issue id="GradleGetter" severity="ignore" /> + <issue id="GradleIdeError" severity="ignore" /> + <issue id="GradleOverrides" severity="ignore" /> + <issue id="GradlePath" severity="ignore" /> + <issue id="GrantAllUris" severity="ignore" /> + <issue id="GridLayout" severity="ignore" /> + <issue id="HandlerLeak" severity="ignore" /> + <issue id="HardcodedDebugMode" severity="ignore" /> + <issue id="HardcodedText" severity="ignore" /> + <issue id="IconColors" severity="ignore" /> + <issue id="IconDensities" severity="ignore" /> + <issue id="IconDipSize" severity="ignore" /> + <issue id="IconDuplicates" severity="ignore" /> + <issue id="IconDuplicatesConfig" severity="ignore" /> + <issue id="IconExtension" severity="ignore" /> + <issue id="IconLauncherShape" severity="ignore" /> + <issue id="IconLocation" severity="ignore" /> + <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="IconMixedNinePatch" severity="ignore" /> + <issue id="IconNoDpi" severity="ignore" /> + <issue id="IconXmlAndPng" severity="ignore" /> + <issue id="IllegalResourceRef" severity="ignore" /> + <issue id="ImpliedQuantity" severity="ignore" /> + <issue id="ImproperProjectLevelStatement" severity="ignore" /> + <issue id="InOrMmUsage" severity="ignore" /> + <issue id="IncludeLayoutParam" severity="ignore" /> + <issue id="InconsistentArrays" severity="ignore" /> + <issue id="InconsistentLayout" severity="ignore" /> + <issue id="InefficientWeight" severity="ignore" /> + <issue id="InflateParams" severity="ignore" /> + <issue id="InlinedApi" severity="ignore" /> + <issue id="InnerclassSeparator" severity="ignore" /> + <issue id="Instantiatable" severity="ignore" /> + <issue id="InvalidId" severity="ignore" /> + <issue id="InvalidPackage" severity="ignore" /> + <issue id="JavascriptInterface" severity="ignore" /> + <issue id="LabelFor" severity="ignore" /> + <issue id="LibraryCustomView" severity="ignore" /> + <issue id="LocalSuppress" severity="ignore" /> + <issue id="LocaleFolder" severity="ignore" /> + <issue id="MangledCRLF" severity="ignore" /> + <issue id="ManifestOrder" severity="ignore" /> + <issue id="ManifestTypo" severity="ignore" /> + <issue id="MenuTitle" severity="ignore" /> + <issue id="MergeRootFrame" severity="ignore" /> + <issue id="MisplacedStatement" severity="ignore" /> + <issue id="MissingApplicationIcon" severity="ignore" /> + <issue id="MissingId" severity="ignore" /> + <issue id="MissingPrefix" severity="ignore" /> + <issue id="MissingQuantity" severity="ignore" /> + <issue id="MissingRegistered" severity="ignore" /> + <issue id="MissingSuperCall" severity="ignore" /> + <issue id="MissingTranslation" severity="ignore" /> + <issue id="MissingVersion" severity="ignore" /> + <issue id="MockLocation" severity="ignore" /> + <issue id="MultipleUsesSdk" severity="ignore" /> + <issue id="NamespaceTypo" severity="ignore" /> + <issue id="NestedScrolling" severity="ignore" /> + <issue id="NestedWeights" severity="ignore" /> + <issue id="NewApi" severity="ignore" /> + <issue id="NfcTechWhitespace" severity="ignore" /> + <issue id="NotSibling" severity="ignore" /> + <issue id="ObsoleteLayoutParam" severity="ignore" /> + <issue id="OldTargetApi" severity="ignore" /> + <issue id="OnClick" severity="ignore" /> + <issue id="Orientation" severity="ignore" /> + <issue id="Overdraw" severity="ignore" /> + <issue id="Override" severity="ignore" /> + <issue id="PackagedPrivateKey" severity="ignore" /> + <issue id="ParcelCreator" severity="ignore" /> + <issue id="PrivateResource" severity="ignore" /> + <issue id="Proguard" severity="ignore" /> + <issue id="ProguardSplit" severity="ignore" /> + <issue id="PropertyEscape" severity="ignore" /> + <issue id="ProtectedPermissions" severity="ignore" /> + <issue id="PxUsage" severity="ignore" /> + <issue id="Recycle" severity="ignore" /> + <issue id="ReferenceType" severity="ignore" /> + <issue id="Registered" severity="ignore" /> + <issue id="RequiredSize" severity="ignore" /> + <issue id="ResAuto" severity="ignore" /> + <issue id="ResourceAsColor" severity="ignore" /> + <issue id="ResourceCycle" severity="ignore" /> + <issue id="ResourceName" severity="ignore" /> + <issue id="RtlCompat" severity="ignore" /> + <issue id="RtlEnabled" severity="ignore" /> + <issue id="RtlHardcoded" severity="ignore" /> + <issue id="RtlSymmetry" severity="ignore" /> + <issue id="ScrollViewCount" severity="ignore" /> + <issue id="ScrollViewSize" severity="ignore" /> + <issue id="SdCardPath" severity="ignore" /> + <issue id="SecureRandom" severity="ignore" /> + <issue id="ServiceCast" severity="ignore" /> + <issue id="SetJavaScriptEnabled" severity="ignore" /> + <issue id="ShowToast" severity="ignore" /> + <issue id="SignatureOrSystemPermissions" severity="ignore" /> + <issue id="SimpleDateFormat" severity="ignore" /> + <issue id="SmallSp" severity="ignore" /> + <issue id="SpUsage" severity="ignore" /> + <issue id="StateListReachable" severity="ignore" /> + <issue id="StringFormatCount" severity="ignore" /> + <issue id="StringFormatInvalid" severity="ignore" /> + <issue id="StringFormatMatches" severity="ignore" /> + <issue id="StringShouldBeInt" severity="ignore" /> + <issue id="Suspicious0dp" severity="ignore" /> + <issue id="SuspiciousImport" severity="ignore" /> + <issue id="TextFields" severity="ignore" /> + <issue id="TextViewEdits" severity="ignore" /> + <issue id="TooDeepLayout" severity="ignore" /> + <issue id="TooManyViews" severity="ignore" /> + <issue id="TrulyRandom" severity="ignore" /> + <issue id="TypographyDashes" severity="ignore" /> + <issue id="TypographyEllipsis" severity="ignore" /> + <issue id="TypographyFractions" severity="ignore" /> + <issue id="TypographyOther" severity="ignore" /> + <issue id="Typos" severity="ignore" /> + <issue id="UniquePermission" severity="ignore" /> + <issue id="UnknownId" severity="ignore" /> + <issue id="UnknownIdInLayout" severity="ignore" /> + <issue id="UnlocalizedSms" severity="ignore" /> + <issue id="UnusedAttribute" severity="ignore" /> + <issue id="UnusedNamespace" severity="ignore" /> + <issue id="UnusedQuantity" severity="ignore" /> + <issue id="UnusedResources" severity="ignore" /> + <issue id="UseCheckPermission" severity="ignore" /> + <issue id="UseCompoundDrawables" severity="ignore" /> + <issue id="UseSparseArrays" severity="ignore" /> + <issue id="UseValueOf" severity="ignore" /> + <issue id="UselessLeaf" severity="ignore" /> + <issue id="UselessParent" severity="ignore" /> + <issue id="UsesMinSdkAttributes" severity="ignore" /> + <issue id="ValidFragment" severity="ignore" /> + <issue id="ViewConstructor" severity="ignore" /> + <issue id="ViewHolder" severity="ignore" /> + <issue id="ViewTag" severity="ignore" /> + <issue id="Wakelock" severity="ignore" /> + <issue id="WebViewLayout" severity="ignore" /> + <issue id="WorldReadableFiles" severity="ignore" /> + <issue id="WorldWriteableFiles" severity="ignore" /> + <issue id="WrongCall" severity="ignore" /> + <issue id="WrongCase" severity="ignore" /> + <issue id="WrongFolder" severity="ignore" /> + <issue id="WrongManifestParent" severity="ignore" /> + <issue id="WrongViewCast" severity="ignore" /> +</lint>
\ No newline at end of file diff --git a/showcaseview/showcaseview.iml b/showcaseview/showcaseview.iml index e47f7c6..4617270 100644 --- a/showcaseview/showcaseview.iml +++ b/showcaseview/showcaseview.iml @@ -4,7 +4,7 @@ <facet type="android" name="Android"> <configuration> <option name="LIBRARY_PROJECT" value="true" /> - <option name="UPDATE_PROPERTY_FILES" value="true" /> + <option name="UPDATE_PROPERTY_FILES" value="false" /> </configuration> </facet> </component> @@ -17,5 +17,203 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> -</module> - + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file diff --git a/tests/.settings/org.eclipse.jdt.core.prefs b/tests/.settings/org.eclipse.jdt.core.prefs index e9dd68c..af15cda 100644 --- a/tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/.settings/org.eclipse.jdt.core.prefs @@ -13,6 +13,7 @@ org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore @@ -36,12 +37,25 @@ org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning @@ -115,12 +129,14 @@ org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 @@ -140,6 +156,7 @@ org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line @@ -185,6 +202,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert @@ -232,6 +250,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=inser org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -250,12 +269,14 @@ org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invoca org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert @@ -279,6 +300,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invoc org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert @@ -306,6 +328,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do n org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert @@ -334,6 +357,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invoc org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert @@ -343,6 +367,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=inser org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert @@ -369,4 +394,5 @@ org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=false org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/tests/.settings/org.eclipse.jdt.ui.prefs b/tests/.settings/org.eclipse.jdt.ui.prefs index 7616a5b..06e562c 100644 --- a/tests/.settings/org.eclipse.jdt.ui.prefs +++ b/tests/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,3 @@ -#Wed Sep 14 20:41:07 CEST 2011 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_cgeo @@ -9,7 +8,7 @@ org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.staticondemandthreshold=99 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false @@ -20,15 +19,17 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=true sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false +sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true @@ -36,15 +37,16 @@ sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=false -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false @@ -52,10 +54,13 @@ sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 690838c..3ffded7 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -5,15 +5,15 @@ android:versionName="1.0" > <uses-sdk - android:minSdkVersion="8" - android:targetSdkVersion="13" /> + android:minSdkVersion="9" + android:targetSdkVersion="19" /> <uses-feature android:name="android.hardware.screen.portrait" android:required="false" /> <instrumentation - android:name="com.zutubi.android.junitreport.JUnitReportTestRunner" + android:name="cgeo.junit.CgeoTestRunner" android:targetPackage="cgeo.geocaching" /> <application @@ -31,4 +31,4 @@ </activity> </application> -</manifest>
\ No newline at end of file +</manifest> diff --git a/tests/ant.properties b/tests/ant.properties index 84cba61..11b92ba 100644 --- a/tests/ant.properties +++ b/tests/ant.properties @@ -18,4 +18,4 @@ tested.project.dir=../main # Use a test runner which can create JUnit compliant XML reports -test.runner=com.zutubi.android.junitreport.JUnitReportTestRunner +test.runner=cgeo.junit.CgeoTestRunner diff --git a/tests/libs/assertj-core-1.5.0.jar b/tests/libs/assertj-core-1.5.0.jar Binary files differdeleted file mode 100644 index 071ccf4..0000000 --- a/tests/libs/assertj-core-1.5.0.jar +++ /dev/null diff --git a/tests/libs/assertj-core-1.7.0.jar b/tests/libs/assertj-core-1.7.0.jar Binary files differnew file mode 100644 index 0000000..1bc46a2 --- /dev/null +++ b/tests/libs/assertj-core-1.7.0.jar diff --git a/tests/libs/docs/robotium-solo-5.1-javadoc.jar b/tests/libs/docs/robotium-solo-5.1-javadoc.jar Binary files differdeleted file mode 100644 index 92ebff2..0000000 --- a/tests/libs/docs/robotium-solo-5.1-javadoc.jar +++ /dev/null diff --git a/tests/libs/espresso-1.1-bundled.jar b/tests/libs/espresso-1.1-bundled.jar Binary files differnew file mode 100644 index 0000000..3a1712a --- /dev/null +++ b/tests/libs/espresso-1.1-bundled.jar diff --git a/tests/libs/robotium-solo-5.1.jar b/tests/libs/robotium-solo-5.1.jar Binary files differdeleted file mode 100644 index 1931dd9..0000000 --- a/tests/libs/robotium-solo-5.1.jar +++ /dev/null diff --git a/tests/libs/robotium-solo-5.1.jar.properties b/tests/libs/robotium-solo-5.1.jar.properties deleted file mode 100644 index 9df11e1..0000000 --- a/tests/libs/robotium-solo-5.1.jar.properties +++ /dev/null @@ -1 +0,0 @@ -doc=./docs/robotium-solo-5.1-javadoc.jar
\ No newline at end of file diff --git a/tests/lint.xml b/tests/lint.xml index 88294aa..ce0d54f 100644 --- a/tests/lint.xml +++ b/tests/lint.xml @@ -2,4 +2,7 @@ <lint> <issue id="Assert" severity="ignore" /> <issue id="IconMissingDensityFolder" severity="ignore" /> + <issue id="InvalidPackage"> + <ignore path="libs/espresso-1.1-bundled.jar" /> + </issue> </lint>
\ No newline at end of file diff --git a/tests/res/layout/cgeo_tests_activity.xml b/tests/res/layout/cgeo_tests_activity.xml index 43225ac..d035210 100644 --- a/tests/res/layout/cgeo_tests_activity.xml +++ b/tests/res/layout/cgeo_tests_activity.xml @@ -13,6 +13,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_gravity="center_vertical" android:gravity="center_vertical" @@ -27,6 +28,7 @@ android:layout_height="fill_parent" android:layout_above="@+id/buttonRun" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_below="@+id/headline" > <TextView @@ -43,6 +45,7 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="false" + android:layout_alignParentStart="false" android:onClick="runTests" android:text="@string/run_tests" /> diff --git a/tests/res/raw/gcvote.xml b/tests/res/raw/gcvote.xml new file mode 100644 index 0000000..c58100a --- /dev/null +++ b/tests/res/raw/gcvote.xml @@ -0,0 +1,13 @@ +<votes userName='' currentVersion='3.2' securityState='locked' loggedIn='false'> +<vote userName='' cacheId='120f6a89-94db-4897-9813-4d79d59ffb09' voteMedian='2.5' voteAvg='2.9' voteCnt='5' voteUser='0' waypoint='GC3MVFN' vote1='0' vote2='3' vote3='1' vote4='1' vote5='0' rawVotes='(2.5:3)(3.0:1)(4.0:1)'/> +<vote userName='' cacheId='3683c154-4a2a-45cd-a20e-ae503ee8975c' voteMedian='2.5' voteAvg='2.75' voteCnt='6' voteUser='0' waypoint='GC3JCQG' vote1='0' vote2='4' vote3='1' vote4='1' vote5='0' rawVotes='(2.0:1)(2.5:3)(3.0:1)(4.0:1)'/> +<vote userName='' cacheId='411fa2e5-7f03-458e-a2e0-f3eda8fd7140' voteMedian='4' voteAvg='4' voteCnt='1' voteUser='0' waypoint='GC2X3X2' vote1='0' vote2='0' vote3='0' vote4='1' vote5='0' rawVotes='(4.0:1)'/> +<vote userName='' cacheId='44f9a8c1-97ac-451a-9269-4b7dc1322db5' voteMedian='3' voteAvg='3.3333333333333' voteCnt='3' voteUser='0' waypoint='GC30X77' vote1='0' vote2='0' vote3='2' vote4='1' vote5='0' rawVotes='(3.0:2)(4.0:1)'/> +<vote userName='' cacheId='5520c33b-3941-45ca-9056-ea655dbaadf7' voteMedian='3.75' voteAvg='3.75' voteCnt='2' voteUser='0' waypoint='GC1WEVZ' vote1='0' vote2='0' vote3='1' vote4='1' vote5='0' rawVotes='(3.5:1)(4.0:1)'/> +<vote userName='' cacheId='5be5cbe3-9094-4a48-b534-dbc52b337315' voteMedian='3.5' voteAvg='3.5' voteCnt='2' voteUser='0' waypoint='GC3JCY7' vote1='0' vote2='0' vote3='1' vote4='1' vote5='0' rawVotes='(3.0:1)(4.0:1)'/> +<vote userName='' cacheId='735334dd-e284-4a7b-bc78-f3534f52a46d' voteMedian='2.5' voteAvg='2.6666666666667' voteCnt='3' voteUser='0' waypoint='GC3QD6N' vote1='0' vote2='2' vote3='1' vote4='0' vote5='0' rawVotes='(2.5:2)(3.0:1)'/> +<vote userName='' cacheId='92a611f9-9ff3-41ac-ae4e-d2927c86e836' voteMedian='3.25' voteAvg='3.5625' voteCnt='8' voteUser='0' waypoint='GCKF13' vote1='0' vote2='0' vote3='5' vote4='2' vote5='1' rawVotes='(3.0:4)(3.5:1)(4.0:2)(5.0:1)'/> +<vote userName='' cacheId='a02894bb-4a08-4c09-a73c-25939894ba15' voteMedian='3' voteAvg='3.1666666666667' voteCnt='9' voteUser='0' waypoint='GC2R3X3' vote1='0' vote2='2' vote3='5' vote4='2' vote5='0' rawVotes='(2.0:1)(2.5:1)(3.0:3)(3.5:2)(4.0:2)'/> +<vote userName='' cacheId='a1711706-09c4-44de-bda8-36df7e53d57c' voteMedian='3.5' voteAvg='3.5' voteCnt='4' voteUser='0' waypoint='GC3MVN6' vote1='0' vote2='0' vote3='2' vote4='2' vote5='0' rawVotes='(3.0:2)(4.0:2)'/> +<errorstring></errorstring> +</votes> diff --git a/tests/res/raw/giga_lab_caches.gpx b/tests/res/raw/giga_lab_caches.gpx new file mode 100644 index 0000000..a18224e --- /dev/null +++ b/tests/res/raw/giga_lab_caches.gpx @@ -0,0 +1,221 @@ +<?xml version="1.0" encoding="utf-8"?>
+<gpx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd" version="1.0" creator="Groundspeak, Inc. All Rights Reserved. http://www.groundspeak.com" xmlns="http://www.topografix.com/GPX/1/0">
+ <name>Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>This is a cache list generated from Labs.Geocaching.com specifically for Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <author>Groundspeak</author>
+ <time>2014-09-06T04:40:43.0556858Z</time>
+ <keywords>lab cache, cache, geocache, groundspeak</keywords>
+ <wpt lat="48.173617" lon="11.553767">
+ <name>01_Munich Olympic Walk Of Stars_Updated-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>01_Munich Olympic Walk Of Stars_Updated (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635824454" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>01_Munich Olympic Walk Of Stars_Updated-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">01_Munich Olympic Walk Of Stars_Updated (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Ein Paar schrge Vgel: Seit 2003 haben sich Berhmtheiten aus Sport, Musik und Unterhaltung mit ihren Hnden im Munich Walk of Stars verewigt. Hier findet man Knstler vereint, die ansonsten an entgegengesetzten Enden des musikalischen Spektrums anzusiedeln sind.
+Frage: Wie lautet der Vorname des Musikers CAT STEVANS, der in unmittelbarer Nhe der schrgen Vgel seine Hnde in den Beton gedrckt hat?
+
+ENG:
+Crazy birds: Since 2003 celebrities from the worlds of sport, music and entertainment have been leaving their marks at the Munich Walk of Stars. Amongst others, artists who one would normally place on opposite ends of the musical spectrum are placed in close neighbourhood.
+Question: What is the first name of the musician CAT STEVANS located directly next to the crazy birds (DEU: Spatzen = ENG: Sparrows)?
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.177983" lon="11.555683">
+ <name>02_BMW-Welt-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>02_BMW-Welt (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635824453" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>02_BMW-Welt-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">02_BMW-Welt (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Doppelkegel & Dachwolke: Seit der Erffnung des Gebudes 2007 hat dessen Architektur diverse Preise gewonnen. Einige Urkunden sind im Eingangsbereich zu besichtigen. Nur eine davon stammt aus dem Jahr 2009.
+Frage: Wie lautet das erste Wort auf der Urkunde (ohne "*" Sternchen)?
+
+ENG:
+Double Cone & Flying Cloud: Since the opening of this building in 2007 its architecture has won several awards. Some of those certificates are on display in the entrance area. Only one of them dates from 2009.
+Question: What is the first word on the certificate (without "*" asterisk)?
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.178867" lon="11.553133">
+ <name>03_Olympisches Dorf-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>03_Olympisches Dorf (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635824452" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>03_Olympisches Dorf-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">03_Olympisches Dorf (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Malen nach Zahlen: Die ehemaligen Wohnungen der Sportler der Olympischen Spiele 1972 werden nun von Studenten bewohnt. Manche haben ihren Bungalow aufwndig bemalt. Ein Gemlde ziert die Rckwand zweier Wohnungen. Auf diesem Gemlde sind beinahe alle Mnchner Sehenswrdigkeiten verewigt.
+Frage: Multipliziere die Ziffern der beiden Hausnummern.
+
+ENG:
+Painting by Numbers: The former athletes' apartments of the Olympic Games 1972 are now being lived in by students. Some of them took great lengths to paint their bungalows. One painting decorates the back wall of two apartments and shows nearly all the main attractions in Munich.
+Question: Multiply the two street numbers of the apartments.
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.179817" lon="11.549333">
+ <name>04_Connollystrasse-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>04_Connollystrasse (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635824451" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>04_Connollystrasse-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">04_Connollystrasse (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Gedenksttte: Am 5. September 1972 nahmen Mitglieder einer palstinensischen Terrororganisation elf israelische Sportler als Geiseln. Bei der Befreiungsaktion kamen alle elf Athleten ums Leben. Eine Gedenktafel erinnert an der Connollystrae 31 an sie.
+Frage: Wie lautet das letzte Wort auf der Gedenktafel im lateinischen Alphabet?
+
+ENG:
+Memorial Site: On September 5th 1972, members of a Palestinian terror organisation took eleven Israeli athletes as hostages. During the attempted rescue all of the eleven athletes lost their lives. They are being remembered at a memorial at Connollystrae 31.
+Question: What is the last word of the memorial in Roman alphabet?
+
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.170083" lon="11.545583">
+ <name>05_Nationenbaum-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>05_Nationenbaum (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635824450" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>05_Nationenbaum-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">05_Nationenbaum (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Typisch Belgisch: Einige der 1972 an den Olympischen Spielen teilnehmenden Nationen haben in diesem Areal Bume gepflanzt. Die von sterreich und San Marino gestifteten Bume sind von der gleichen Art.
+Frage: Wie lautet das Wort, das im lateinischen Namen doppelt vorkommt?
+
+ENG:
+Typically Belgian: Some of the participating countries in the 1972 Olympic Games planted trees in this area. The trees donated by Austria and San Marino are of the same species.
+Question: Name the word occurring twice in the Latin name.
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.173283" lon="11.5506">
+ <name>06_Theatron-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>06_Theatron (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635668281" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>06_Theatron-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">06_Theatron (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Seebhne: Auf einer kleinen Halbinsel im Olympiasee befindet sich eine Seebhne, umgeben von den Steinstufen des viertelrunden Theatron. Schaue von der Tribne aus in Richtung Olympiaturm.
+Frage: Schaue von der Tribne aus in Richtung Olympiaturm. Wie viele Schwimmer siehst Du?
+
+
+ENG:
+Lake Placid: Situated on a small peninsula of the Olympic Lake is a small stage, surrounded by the stone steps of the Theatron.Take a look from the stands in the direction of the Olympic Tower.
+Question: How many swimmers do you see?
+
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.16985" lon="11.55155">
+ <name>07_Olympiaberg-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>07_Olympiaberg (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635668280" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>07_Olympiaberg-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">07_Olympiaberg (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Mnchner Alpen: Der Olympiaberg entstand zwischen 1947 und 1958 aus Trmmern des Zweiten Weltkrieges. Vom Gipfel aus siehst Du die weltberhmte Architektur des Olympiastadions, der Olympiahalle und der Olympiaschwimmhalle.
+Frage: Wie viele "Zeltstangen" ragen mit ihren Kpfen ber den Horizont?
+
+ENG:
+Munich Alps: The Olympiaberg was piled up between 1947 and 1958 from rubble left after World War II. From the summit you get a great view of the world renowned architecture of the Olympic Stadium, the Olympic Hall and the Olympic Swimming Pool.
+Question: How many "tent poles" raise their heads above the horizon?
+
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.1702" lon="11.546217">
+ <name>08_Engelbaum-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>08_Engelbaum (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635668279" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>08_Engelbaum-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">08_Engelbaum (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Pltzlich war er da - der Spender dieser Figur bleibt auch Jahre nach der Installation unbekannt. Der Engel im Baum trgt ein Instrument im Arm. Gesucht ist der englische Name des Instruments.
+Frage: Welches Instrument trgt der Engel (engl.)?
+
+ENG:
+An angel in a tree - no one knows when or who placed this religious figure here. Have a look at it - and name the instrument which is laying in the angel arms.
+Question: The angel holds an instrument. Name it.
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.1744" lon="11.551917">
+ <name>09_Gruselkabinett-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>09_Gruselkabinett (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635668278" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>09_Gruselkabinett-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">09_Gruselkabinett (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Ein Knstler zeigt hier erstaunliche Einblicke in den menschlichen Krper. Mit einer als Plastinat bekannten Methode zeigt er, wie der menschliche Krper ohne Haut aussieht. Sehenswert und kurios. Wenn Du die Zeit hast, dann unbedingt mitnehmen.
+Frage: Vorname des Plastinators, der hier eine Ausstellung macht.
+
+ENG:
+An artist of plastination presents his work here. A view inside the human body in an extreme stylish way. Please have a look at the exhibition. It is special!
+Question: First name of the initiator of the exhibition.
+-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+ <wpt lat="48.17085" lon="11.556083">
+ <name>10_Schuttblume-Project MUNICH2014 - Mia san Giga! Olympiapark</name>
+ <desc>10_Schuttblume (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</desc>
+ <sym>Geocache</sym>
+ <groundspeak:cache id="-635668277" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
+ <groundspeak:name>10_Schuttblume-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:name>
+ <groundspeak:owner id="0" />
+ <groundspeak:type>Geocache|Lab Cache</groundspeak:type>
+ <groundspeak:difficulty>0</groundspeak:difficulty>
+ <groundspeak:terrain>0</groundspeak:terrain>
+ <groundspeak:short_description html="false">10_Schuttblume (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark</groundspeak:short_description>
+ <groundspeak:long_description html="false">DEU:
+Die Schuttblume ist ein den zivilen Luftkriegsopfern des Zweiten Weltkrieges gewidmetes Mahnmal auf dem Olympiaberg, das zu den Olympischen Spielen 1972 vom Deutschen Gewerkschaftsbund und der Landeshauptstadt Mnchen gestiftet wurde
+Frage: Gedenktafel am Boden - letztes Wort ist gesucht
+
+ENG:
+The Schuttblume (engl.Flower made of rubble) is a memorial side. It is dedicated to all the victims of the Second World War air war. It was donated 1972 during the Olympics.
+Question: plaque on the ground - last word is...-DEU: LAB Caches zum Project MUNICH2014 - Mia san Giga! Olympia Stadion</groundspeak:long_description>
+ </groundspeak:cache>
+ </wpt>
+</gpx>
\ No newline at end of file diff --git a/tests/res/raw/own_cache.htm b/tests/res/raw/own_cache.htm index 4d26e2e..c222bcd 100644 --- a/tests/res/raw/own_cache.htm +++ b/tests/res/raw/own_cache.htm @@ -424,7 +424,7 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet <div id="ctl00_ContentBody_mcd2">
Hidden
:
- 31/Mar/2012
+ 2013-03-31
</div>
<div>
diff --git a/tests/src/cgeo/CGeoTestCase.java b/tests/src/cgeo/CGeoTestCase.java index 5759bc7..2dbac3d 100644 --- a/tests/src/cgeo/CGeoTestCase.java +++ b/tests/src/cgeo/CGeoTestCase.java @@ -2,6 +2,7 @@ package cgeo; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.DataStore; +import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag; import cgeo.geocaching.settings.Settings; @@ -28,14 +29,12 @@ public abstract class CGeoTestCase extends ApplicationTestCase<CgeoApplication> } /** Remove cache from DB and cache to ensure that the cache is not loaded from the database */ - protected static void deleteCacheFromDB(String geocode) { + protected static void deleteCacheFromDB(final String geocode) { DataStore.removeCache(geocode, LoadFlags.REMOVE_ALL); } /** * remove cache from database and file system - * - * @param geocode */ protected static void removeCacheCompletely(final String geocode) { final EnumSet<RemoveFlag> flags = EnumSet.copyOf(LoadFlags.REMOVE_ALL); @@ -44,6 +43,17 @@ public abstract class CGeoTestCase extends ApplicationTestCase<CgeoApplication> } /** + * Remove completely the previous instance of a cache, then save this object into the database + * and the cache cache. + * + * @param cache the fresh cache to save + */ + protected static void saveFreshCacheToDB(final Geocache cache) { + removeCacheCompletely(cache.getGeocode()); + DataStore.saveCache(cache, LoadFlags.SAVE_ALL); + } + + /** * must be called once before setting the flags * can be called again after restoring the flags */ @@ -59,10 +69,8 @@ public abstract class CGeoTestCase extends ApplicationTestCase<CgeoApplication> /** * can be called after recordMapStoreFlags, * to set the flags for map storing as necessary - * @param storeCacheMap - * @param storeWpMaps */ - protected void setMapStoreFlags(boolean storeCacheMap, boolean storeWpMaps) { + protected void setMapStoreFlags(final boolean storeCacheMap, final boolean storeWpMaps) { if (!oldMapStoreFlagsRecorded) { throw new IllegalStateException("Previous MapStoreFlags havn't been recorded! Setting not allowed"); } diff --git a/tests/src/cgeo/geocaching/CgeoApplicationTest.java b/tests/src/cgeo/geocaching/CgeoApplicationTest.java index de3f4ba..6763d7b 100644 --- a/tests/src/cgeo/geocaching/CgeoApplicationTest.java +++ b/tests/src/cgeo/geocaching/CgeoApplicationTest.java @@ -9,14 +9,14 @@ import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.connector.gc.MapTokens; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.loaders.RecaptchaReceiver; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; +import cgeo.geocaching.maps.LivemapStrategy; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.TestSettings; import cgeo.geocaching.test.RegExPerformanceTest; @@ -72,7 +72,7 @@ public class CgeoApplicationTest extends CGeoTestCase { public static void testSearchTrackable() { final Trackable tb = GCParser.searchTrackable("TB2J1VZ", null, null); assertThat(tb).isNotNull(); - assert (tb != null); // eclipse bug + assert tb != null; // eclipse bug // fix data assertThat(tb.getGuid()).isEqualTo("aefffb86-099f-444f-b132-605436163aa8"); assertThat(tb.getGeocode()).isEqualTo("TB2J1VZ"); @@ -85,7 +85,8 @@ public class CgeoApplicationTest extends CGeoTestCase { assertThat(tb.getOwnerGuid()).isEqualTo("0564a940-8311-40ee-8e76-7e91b2cf6284"); assertThat(tb.getGoal()).isEqualTo("Kinder erfreuen.<br /><br />Make children happy."); assertThat(tb.getDetails()).startsWith("Auf der CD sind"); - assertThat(tb.getImage()).isEqualTo("http://imgcdn.geocaching.com/track/large/38382780-87a7-4393-8393-78841678ee8c.jpg"); + // the host of the image can vary + assertThat(tb.getImage()).endsWith("geocaching.com/track/large/38382780-87a7-4393-8393-78841678ee8c.jpg"); // Following data can change over time assertThat(tb.getDistance()).isGreaterThanOrEqualTo(10617.8f); assertThat(tb.getLogs().size()).isGreaterThanOrEqualTo(10); @@ -94,7 +95,7 @@ public class CgeoApplicationTest extends CGeoTestCase { // no assumption possible: assertThat(tb.getSpottedName()).isEqualTo("Nice place for a break cache"); // we can't check specifics in the log entries since they change, but we can verify data was parsed - for (LogEntry log : tb.getLogs()) { + for (final LogEntry log : tb.getLogs()) { assertThat(log.date).isGreaterThan(0); assertThat(log.author).isNotEmpty(); if (log.type == LogType.PLACED_IT || log.type == LogType.RETRIEVED_IT) { @@ -107,7 +108,7 @@ public class CgeoApplicationTest extends CGeoTestCase { } /** - * Test {@link GCParser#searchByGeocode(String, String, int, boolean, CancellableHandler)} + * Test {@link Geocache#searchByGeocode(String, String, int, boolean, CancellableHandler)} */ @MediumTest public static Geocache testSearchByGeocode(final String geocode) { @@ -135,7 +136,6 @@ public class CgeoApplicationTest extends CGeoTestCase { /** * Set the login data to the cgeo login, run the given Runnable, and restore the login. * - * @param runnable */ private static void withMockedLoginDo(final Runnable runnable) { final ImmutablePair<String, String> login = Settings.getGcCredentials(); @@ -165,14 +165,14 @@ public class CgeoApplicationTest extends CGeoTestCase { deleteCacheFromDBAndLogout(cache.getGeocode()); - SearchResult search = Geocache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); + SearchResult search = Geocache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST.id, true, null); assertThat(search).isNotNull(); assertThat(search.getGeocodes()).hasSize(1); assertThat(search.getGeocodes().contains(cache.getGeocode())).isTrue(); final Geocache searchedCache = search.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); // coords must be null if the user is not logged in assertThat(searchedCache).isNotNull(); - assert (searchedCache != null); // eclipse bug + assert searchedCache != null; // eclipse bug assertThat(searchedCache.getCoords()).isNull(); // premium cache. Not visible to guests @@ -180,7 +180,7 @@ public class CgeoApplicationTest extends CGeoTestCase { deleteCacheFromDBAndLogout(cache.getGeocode()); - search = Geocache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); + search = Geocache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST.id, true, null); assertThat(search).isNotNull(); assertThat(search.getGeocodes()).isEmpty(); } @@ -201,7 +201,7 @@ public class CgeoApplicationTest extends CGeoTestCase { deleteCacheFromDBAndLogout(cache.getGeocode()); - final SearchResult search = Geocache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST_ID, true, null); + final SearchResult search = Geocache.searchByGeocode(cache.getGeocode(), null, StoredList.TEMPORARY_LIST.id, true, null); assertThat(search).isNotNull(); assertThat(search.getGeocodes()).isEmpty(); } @@ -211,9 +211,8 @@ public class CgeoApplicationTest extends CGeoTestCase { /** * mock the "exclude disabled caches" and "exclude my caches" options for the execution of the runnable * - * @param runnable */ - private static void withMockedFilters(Runnable runnable) { + private static void withMockedFilters(final Runnable runnable) { // backup user settings final boolean excludeMine = Settings.isExcludeMyCaches(); final boolean excludeDisabled = Settings.isExcludeDisabledCaches(); @@ -276,14 +275,14 @@ public class CgeoApplicationTest extends CGeoTestCase { public void run() { final SearchResult search = GCParser.searchByUsername("blafoo", CacheType.WEBCAM, false, null); assertThat(search).isNotNull(); - assertThat(search.getTotalCountGC()).isEqualTo(4); + assertThat(search.getTotalCountGC()).isEqualTo(5); assertThat(search.getGeocodes().contains("GCP0A9")).isTrue(); } }); } /** - * Test {@link ConnectorFactory#searchByViewport(Viewport, String)} + * Test {@link ConnectorFactory#searchByViewport(Viewport, MapTokens)} */ @MediumTest public static void testSearchByViewport() { @@ -292,7 +291,7 @@ public class CgeoApplicationTest extends CGeoTestCase { @Override public void run() { // backup user settings - final Strategy strategy = Settings.getLiveMapStrategy(); + final LivemapStrategy strategy = Settings.getLiveMapStrategy(); final CacheType cacheType = Settings.getCacheType(); try { @@ -307,23 +306,27 @@ public class CgeoApplicationTest extends CGeoTestCase { final Viewport viewport = new Viewport(mockedCache, 0.003, 0.003); // check coords for DETAILED - Settings.setLiveMapStrategy(Strategy.DETAILED); + Settings.setLiveMapStrategy(LivemapStrategy.DETAILED); SearchResult search = ConnectorFactory.searchByViewport(viewport, tokens); assertThat(search).isNotNull(); assertThat(search.getGeocodes().contains(mockedCache.getGeocode())).isTrue(); Geocache parsedCache = DataStore.loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + assert parsedCache != null; + assertThat(parsedCache).isNotNull(); assertThat(mockedCache.getCoords().equals(parsedCache.getCoords())).isEqualTo(Settings.isGCPremiumMember()); assertThat(parsedCache.isReliableLatLon()).isEqualTo(Settings.isGCPremiumMember()); // check update after switch strategy to FAST - Settings.setLiveMapStrategy(Strategy.FAST); + Settings.setLiveMapStrategy(LivemapStrategy.FAST); Tile.cache.removeFromTileCache(mockedCache); search = ConnectorFactory.searchByViewport(viewport, tokens); assertThat(search).isNotNull(); assertThat(search.getGeocodes().contains(mockedCache.getGeocode())).isTrue(); parsedCache = DataStore.loadCache(mockedCache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + assert parsedCache != null; + assertThat(parsedCache).isNotNull(); assertThat(mockedCache.getCoords().equals(parsedCache.getCoords())).isEqualTo(Settings.isGCPremiumMember()); assertThat(parsedCache.isReliableLatLon()).isEqualTo(Settings.isGCPremiumMember()); @@ -338,7 +341,7 @@ public class CgeoApplicationTest extends CGeoTestCase { } /** - * Test {@link ConnectorFactory#searchByViewport(Viewport, String)} + * Test {@link ConnectorFactory#searchByViewport(Viewport, MapTokens)} */ @MediumTest public static void testSearchByViewportNotLoggedIn() { @@ -346,8 +349,8 @@ public class CgeoApplicationTest extends CGeoTestCase { @Override public void run() { - final Strategy strategy = Settings.getLiveMapStrategy(); - final Strategy testStrategy = Strategy.FAST; // FASTEST, FAST or DETAILED for tests + final LivemapStrategy strategy = Settings.getLiveMapStrategy(); + final LivemapStrategy testStrategy = LivemapStrategy.FAST; // FASTEST, FAST or DETAILED for tests Settings.setLiveMapStrategy(testStrategy); final CacheType cacheType = Settings.getCacheType(); @@ -366,11 +369,13 @@ public class CgeoApplicationTest extends CGeoTestCase { assertThat(search.getGeocodes().contains(cache.getGeocode())).isTrue(); // coords differ final Geocache cacheFromViewport = DataStore.loadCache(cache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB); + assert cacheFromViewport != null; + assertThat(cacheFromViewport).isNotNull(); Log.d("cgeoApplicationTest.testSearchByViewportNotLoggedIn: Coords expected = " + cache.getCoords()); Log.d("cgeoApplicationTest.testSearchByViewportNotLoggedIn: Coords actual = " + cacheFromViewport.getCoords()); assertThat(cache.getCoords().distanceTo(cacheFromViewport.getCoords()) <= 1e-3).isFalse(); // depending on the chosen strategy the coords can be reliable or not - assertThat(cacheFromViewport.isReliableLatLon()).isEqualTo(testStrategy == Strategy.DETAILED); + assertThat(cacheFromViewport.isReliableLatLon()).isEqualTo(testStrategy == LivemapStrategy.DETAILED); // premium cache cache = new GC2JVEH(); @@ -395,18 +400,12 @@ public class CgeoApplicationTest extends CGeoTestCase { * Test cache parsing. Esp. useful after a GC.com update */ public static void testSearchByGeocodeBasis() { - for (MockedCache mockedCache : RegExPerformanceTest.MOCKED_CACHES) { - String oldUser = mockedCache.getMockedDataUser(); + for (final MockedCache mockedCache : RegExPerformanceTest.MOCKED_CACHES) { + final String oldUser = mockedCache.getMockedDataUser(); try { mockedCache.setMockedDataUser(Settings.getUsername()); - Geocache parsedCache = CgeoApplicationTest.testSearchByGeocode(mockedCache.getGeocode()); - if (null != parsedCache) { - // fake found flag for one cache until it will be updated - if (parsedCache.getGeocode().equals("GC3XX5J") && Settings.getUsername().equals("mucek4")) { - parsedCache.setFound(false); - } - Compare.assertCompareCaches(mockedCache, parsedCache, true); - } + final Geocache parsedCache = CgeoApplicationTest.testSearchByGeocode(mockedCache.getGeocode()); + Compare.assertCompareCaches(mockedCache, parsedCache, true); } finally { mockedCache.setMockedDataUser(oldUser); } @@ -425,7 +424,7 @@ public class CgeoApplicationTest extends CGeoTestCase { } /** Remove cache from DB and cache to ensure that the cache is not loaded from the database */ - private static void deleteCacheFromDBAndLogout(String geocode) { + private static void deleteCacheFromDBAndLogout(final String geocode) { deleteCacheFromDB(geocode); GCLogin.getInstance().logout(); diff --git a/tests/src/cgeo/geocaching/DataStoreTest.java b/tests/src/cgeo/geocaching/DataStoreTest.java index 3579cc5..9ef5dda 100644 --- a/tests/src/cgeo/geocaching/DataStoreTest.java +++ b/tests/src/cgeo/geocaching/DataStoreTest.java @@ -8,9 +8,9 @@ import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import org.apache.commons.lang3.StringUtils; @@ -59,6 +59,7 @@ public class DataStoreTest extends CGeoTestCase { // get list final StoredList list1 = DataStore.getList(listId1); + assertThat(list1).isNotNull(); assertThat(list1.title).isEqualTo("DataStore Test (renamed)"); // move to list (cache1=listId2, cache2=listId2) @@ -123,6 +124,8 @@ public class DataStoreTest extends CGeoTestCase { try { DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB)); final Geocache loadedCache = DataStore.loadCache(GEOCODE_CACHE, LoadFlags.LOAD_ALL_DB_ONLY); + assert loadedCache != null; + assertThat(loadedCache).isNotNull(); assertThat(loadedCache).overridingErrorMessage("Cache was not saved.").isNotNull(); assertThat(loadedCache.getInventory()).hasSize(1); } finally { diff --git a/tests/src/cgeo/geocaching/DestinationTest.java b/tests/src/cgeo/geocaching/DestinationTest.java index 00249c4..9883a32 100644 --- a/tests/src/cgeo/geocaching/DestinationTest.java +++ b/tests/src/cgeo/geocaching/DestinationTest.java @@ -2,7 +2,7 @@ package cgeo.geocaching; import static org.assertj.core.api.Assertions.assertThat; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.test.AndroidTestCase; diff --git a/tests/src/cgeo/geocaching/GeocacheTest.java b/tests/src/cgeo/geocaching/GeocacheTest.java index b3ec6be..26c677d 100644 --- a/tests/src/cgeo/geocaching/GeocacheTest.java +++ b/tests/src/cgeo/geocaching/GeocacheTest.java @@ -5,13 +5,14 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.list.StoredList; +import cgeo.geocaching.location.Geopoint; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -66,13 +67,12 @@ public class GeocacheTest extends CGeoTestCase { } private void assertWaypointsParsed(final String note, final int expectedWaypoints) { - recordMapStoreFlags(); try { setMapStoreFlags(false, false); - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); final String geocode = "Test" + System.nanoTime(); cache.setGeocode(geocode); cache.setWaypoints(new ArrayList<Waypoint>(), false); @@ -86,7 +86,7 @@ public class GeocacheTest extends CGeoTestCase { assertThat(waypoint.getCoords()).isEqualTo(new Geopoint("N51 13.888 E007 03.444")); // assertThat(waypoint.getNote()).isEqualTo("Test"); assertThat(waypoint.getName()).isEqualTo(CgeoApplication.getInstance().getString(R.string.cache_personal_note) + " 1"); - cache.store(StoredList.TEMPORARY_LIST_ID, null); + cache.store(StoredList.TEMPORARY_LIST.id, null); } removeCacheCompletely(geocode); } finally { @@ -94,52 +94,106 @@ public class GeocacheTest extends CGeoTestCase { } } - public static void testMergeDownloadedStored() { + public static void testMergeDownloaded() { + final Geocache previous = new Geocache(); + previous.setGeocode("GC12345"); + previous.setDetailed(true); + previous.setDisabled(true); + previous.setType(CacheType.TRADITIONAL); + previous.setCoords(new Geopoint(40.0, 8.0)); + previous.setDescription("Test1"); + previous.setAttributes(Collections.singletonList("TestAttribute")); + previous.setShortDescription("Short"); + previous.setHint("Hint"); + removeCacheCompletely(previous.getGeocode()); + + final Geocache download = new Geocache(); + download.setGeocode("GC12345"); + download.setDetailed(true); + download.setDisabled(false); + download.setType(CacheType.MULTI); + download.setCoords(new Geopoint(41.0, 9.0)); + download.setDescription("Test2"); - Geocache stored = new Geocache(); + download.gatherMissingFrom(previous); + + assertThat(download.isDetailed()).as("merged detailed").isTrue(); + assertThat(download.isDisabled()).as("merged disabled").isFalse(); + assertThat(download.getType()).as("merged download").isEqualTo(CacheType.MULTI); + assertThat(download.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(41.0, 9.0)); + assertThat(download.getDescription()).as("merged description").isEqualTo("Test2"); + assertThat(download.getShortDescription()).as("merged short description").isEmpty(); + assertThat(download.getAttributes()).as("merged attributes").isEmpty(); + assertThat(download.getHint()).as("merged hint").isEmpty(); + } + + public static void testMergeDownloadedStored() { + final Geocache stored = new Geocache(); stored.setGeocode("GC12345"); stored.setDetailed(true); stored.setDisabled(true); stored.setType(CacheType.TRADITIONAL); stored.setCoords(new Geopoint(40.0, 8.0)); stored.setDescription("Test1"); - ArrayList<String> attributes = new ArrayList<String>(1); - attributes.add("TestAttribute"); - stored.setAttributes(attributes); + stored.setAttributes(Collections.singletonList("TestAttribute")); stored.setShortDescription("Short"); stored.setHint("Hint"); + saveFreshCacheToDB(stored); - Geocache download = new Geocache(); + final Geocache download = new Geocache(); download.setGeocode("GC12345"); download.setDetailed(true); download.setDisabled(false); download.setType(CacheType.MULTI); download.setCoords(new Geopoint(41.0, 9.0)); download.setDescription("Test2"); + download.setAttributes(Collections.<String>emptyList()); download.gatherMissingFrom(stored); assertThat(download.isDetailed()).as("merged detailed").isTrue(); assertThat(download.isDisabled()).as("merged disabled").isFalse(); - assertEquals("Type not merged correctly", CacheType.MULTI, download.getType()); - assertEquals("Longitude not merged correctly", 9.0, download.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 41.0, download.getCoords().getLatitude(), 0.1); - assertEquals("Description not merged correctly", "Test2", download.getDescription()); - assertEquals("ShortDescription not merged correctly", "", download.getShortDescription()); - assertEquals("Attributes not merged correctly", new ArrayList<String>(0), download.getAttributes()); - assertEquals("Hint not merged correctly", "", download.getHint()); + assertThat(download.getType()).as("merged download").isEqualTo(CacheType.MULTI); + assertThat(download.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(41.0, 9.0)); + assertThat(download.getDescription()).as("merged description").isEqualTo("Test2"); + assertThat(download.getShortDescription()).as("merged short description").isEmpty(); + assertThat(download.getAttributes()).as("merged attributes").isEmpty(); + assertThat(download.getHint()).as("merged hint").isEmpty(); } - public static void testMergeLivemapStored() { + public static void testMergeLivemap() { + final Geocache previous = new Geocache(); + previous.setGeocode("GC12345"); + previous.setDetailed(true); + previous.setDisabled(true); + previous.setType(CacheType.TRADITIONAL); + previous.setCoords(new Geopoint(40.0, 8.0)); + removeCacheCompletely(previous.getGeocode()); + + final Geocache livemap = new Geocache(); + livemap.setGeocode("GC12345"); + livemap.setType(CacheType.MULTI, 12); + livemap.setCoords(new Geopoint(41.0, 9.0), 12); + + livemap.gatherMissingFrom(previous); + + assertThat(livemap.isDetailed()).as("merged detailed").isTrue(); + assertThat(livemap.isDisabled()).as("merged disabled").isTrue(); + assertThat(livemap.getType()).as("merged type").isEqualTo(CacheType.TRADITIONAL); + assertThat(livemap.getCoords()).as("merged coordinates").isEqualToComparingFieldByField(new Geopoint(40.0, 8.0)); + assertThat(livemap.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(previous.getCoordZoomLevel()); + } - Geocache stored = new Geocache(); + public static void testMergeLivemapStored() { + final Geocache stored = new Geocache(); stored.setGeocode("GC12345"); stored.setDetailed(true); stored.setDisabled(true); stored.setType(CacheType.TRADITIONAL); stored.setCoords(new Geopoint(40.0, 8.0)); + saveFreshCacheToDB(stored); - Geocache livemap = new Geocache(); + final Geocache livemap = new Geocache(); livemap.setGeocode("GC12345"); livemap.setType(CacheType.MULTI, 12); livemap.setCoords(new Geopoint(41.0, 9.0), 12); @@ -148,90 +202,81 @@ public class GeocacheTest extends CGeoTestCase { assertThat(livemap.isDetailed()).as("merged detailed").isTrue(); assertThat(livemap.isDisabled()).as("merged disabled").isTrue(); - assertEquals("Type not merged correctly", CacheType.TRADITIONAL, livemap.getType()); - assertEquals("Longitude not merged correctly", 8.0, livemap.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, livemap.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", stored.getCoordZoomLevel(), livemap.getCoordZoomLevel()); + assertThat(livemap.getType()).as("merged type").isEqualTo(CacheType.TRADITIONAL); + assertThat(livemap.getCoords()).as("merged coordinates").isEqualToComparingFieldByField(new Geopoint(40.0, 8.0)); + assertThat(livemap.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(stored.getCoordZoomLevel()); } public static void testMergeLivemapZoomin() { - - Geocache livemapFirst = new Geocache(); + final Geocache livemapFirst = new Geocache(); livemapFirst.setGeocode("GC12345"); livemapFirst.setType(CacheType.TRADITIONAL); livemapFirst.setCoords(new Geopoint(40.0, 8.0), 11); - Geocache livemapSecond = new Geocache(); + final Geocache livemapSecond = new Geocache(); livemapSecond.setGeocode("GC12345"); livemapSecond.setType(CacheType.MULTI); livemapSecond.setCoords(new Geopoint(41.0, 9.0), 12); livemapSecond.gatherMissingFrom(livemapFirst); - assertEquals("Type not merged correctly", CacheType.MULTI, livemapSecond.getType()); - assertEquals("Longitude not merged correctly", 9.0, livemapSecond.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 41.0, livemapSecond.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", 12, livemapSecond.getCoordZoomLevel()); + assertThat(livemapSecond.getType()).as("merged type").isEqualTo(CacheType.MULTI); + assertThat(livemapSecond.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(41.0, 9.0)); + assertThat(livemapSecond.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testMergeLivemapZoomout() { - - Geocache livemapFirst = new Geocache(); + final Geocache livemapFirst = new Geocache(); livemapFirst.setGeocode("GC12345"); livemapFirst.setType(CacheType.TRADITIONAL, 12); livemapFirst.setCoords(new Geopoint(40.0, 8.0), 12); - Geocache livemapSecond = new Geocache(); + final Geocache livemapSecond = new Geocache(); livemapSecond.setGeocode("GC12345"); livemapSecond.setType(CacheType.MULTI, 11); livemapSecond.setCoords(new Geopoint(41.0, 9.0), 11); livemapSecond.gatherMissingFrom(livemapFirst); - assertEquals("Type not merged correctly", CacheType.TRADITIONAL, livemapSecond.getType()); - assertEquals("Longitude not merged correctly", 8.0, livemapSecond.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, livemapSecond.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", 12, livemapSecond.getCoordZoomLevel()); + assertThat(livemapSecond.getType()).as("merged type").isEqualTo(CacheType.TRADITIONAL); + assertThat(livemapSecond.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(40.0, 8.0)); + assertThat(livemapSecond.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testMergePopupLivemap() { - - Geocache livemap = new Geocache(); + final Geocache livemap = new Geocache(); livemap.setGeocode("GC12345"); livemap.setCoords(new Geopoint(40.0, 8.0), 12); livemap.setFound(true); - Geocache popup = new Geocache(); + final Geocache popup = new Geocache(); popup.setGeocode("GC12345"); popup.setType(CacheType.MULTI); popup.gatherMissingFrom(livemap); - assertEquals("Type not merged correctly", CacheType.MULTI, popup.getType()); - assertEquals("Longitude not merged correctly", 8.0, popup.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, popup.getCoords().getLatitude(), 0.1); - assertThat(popup.isFound()).overridingErrorMessage("Found not merged correctly").isTrue(); - assertEquals("Zoomlevel not merged correctly", 12, popup.getCoordZoomLevel()); + assertThat(popup.getType()).as("merged type").isEqualTo(CacheType.MULTI); + assertThat(popup.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(40.0, 8.0)); + assertThat(popup.isFound()).overridingErrorMessage("merged found").isTrue(); + assertThat(popup.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testMergeLivemapBMSearched() { - - Geocache bmsearched = new Geocache(); + final Geocache bmsearched = new Geocache(); bmsearched.setGeocode("GC12345"); - Geocache livemap = new Geocache(); + final Geocache livemap = new Geocache(); livemap.setGeocode("GC12345"); livemap.setCoords(new Geopoint(40.0, 8.0), 12); livemap.gatherMissingFrom(bmsearched); - assertEquals("Longitude not merged correctly", 8.0, livemap.getCoords().getLongitude(), 0.1); - assertEquals("Latitude not merged correctly", 40.0, livemap.getCoords().getLatitude(), 0.1); - assertEquals("Zoomlevel not merged correctly", 12, livemap.getCoordZoomLevel()); + assertThat(livemap.getCoords()).as("merged coordinates").isEqualTo(new Geopoint(40.0, 8.0)); + assertThat(livemap.getCoordZoomLevel()).as("merged zoomlevel").isEqualTo(12); } public static void testNameForSorting() { - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); cache.setName("GR8 01-01"); assertThat(cache.getNameForSorting()).isEqualTo("GR000008 000001-000001"); } @@ -250,14 +295,15 @@ public class GeocacheTest extends CGeoTestCase { assertTime("<u><em>Uhrzeit:</em></u> 17-20 " + timeHours + "</span></strong>", 17, 00); assertTime("von 11 bis 13 " + timeHours, 11, 00); assertTime("from 11 to 13 " + timeHours, 11, 00); + assertTime("von 19.15 " + timeHours + " bis ca.20.30 " + timeHours + " statt", 19, 15); } public static void testGuessEventTimeShortDescription() { - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); cache.setType(CacheType.EVENT); cache.setDescription(StringUtils.EMPTY); cache.setShortDescription("text 14:20 text"); - assertThat(cache.guessEventTimeMinutes()).isEqualTo(String.valueOf(14 * 60 + 20)); + assertThat(cache.guessEventTimeMinutes()).isEqualTo(14 * 60 + 20); } private static void assertTime(final String description, final int hours, final int minutes) { @@ -265,24 +311,24 @@ public class GeocacheTest extends CGeoTestCase { cache.setDescription(description); cache.setType(CacheType.EVENT); final int minutesAfterMidnight = hours * 60 + minutes; - assertThat(cache.guessEventTimeMinutes()).isEqualTo(String.valueOf(minutesAfterMidnight)); + assertThat(cache.guessEventTimeMinutes()).isEqualTo(minutesAfterMidnight); } private static void assertNoTime(final String description) { final Geocache cache = new Geocache(); cache.setDescription(description); cache.setType(CacheType.EVENT); - assertThat(cache.guessEventTimeMinutes()).isNull(); + assertThat(cache.guessEventTimeMinutes()).isEqualTo(-1); } public static void testGetPossibleLogTypes() throws Exception { - Geocache gcCache = new Geocache(); + final Geocache gcCache = new Geocache(); gcCache.setGeocode("GC123"); gcCache.setType(CacheType.WEBCAM); assertThat(gcCache.getPossibleLogTypes()).as("possible GC cache log types").contains(LogType.WEBCAM_PHOTO_TAKEN); assertThat(gcCache.getPossibleLogTypes()).as("possible GC cache log types").contains(LogType.NEEDS_MAINTENANCE); - Geocache ocCache = new Geocache(); + final Geocache ocCache = new Geocache(); ocCache.setGeocode("OC1234"); ocCache.setType(CacheType.TRADITIONAL); assertThat(ocCache.getPossibleLogTypes()).as("traditional cache possible log types").doesNotContain(LogType.WEBCAM_PHOTO_TAKEN); @@ -290,24 +336,24 @@ public class GeocacheTest extends CGeoTestCase { } public static void testLogTypeEventPast() throws Exception { - Calendar today = Calendar.getInstance(); + final Calendar today = Calendar.getInstance(); today.add(Calendar.DAY_OF_MONTH, -1); assertThat(createEventCache(today).getDefaultLogType()).isEqualTo(LogType.ATTENDED); } public static void testLogTypeEventToday() throws Exception { - Calendar today = Calendar.getInstance(); + final Calendar today = Calendar.getInstance(); assertThat(createEventCache(today).getDefaultLogType()).isEqualTo(LogType.ATTENDED); } public static void testLogTypeEventFuture() throws Exception { - Calendar today = Calendar.getInstance(); + final Calendar today = Calendar.getInstance(); today.add(Calendar.DAY_OF_MONTH, 1); assertThat(createEventCache(today).getDefaultLogType()).isEqualTo(LogType.WILL_ATTEND); } - private static Geocache createEventCache(Calendar calendar) { - Geocache cache = new Geocache(); + private static Geocache createEventCache(final Calendar calendar) { + final Geocache cache = new Geocache(); cache.setType(CacheType.EVENT); cache.setHidden(calendar.getTime()); return cache; diff --git a/tests/src/cgeo/geocaching/SettingsTest.java b/tests/src/cgeo/geocaching/SettingsTest.java index 4c342b3..c210ab7 100644 --- a/tests/src/cgeo/geocaching/SettingsTest.java +++ b/tests/src/cgeo/geocaching/SettingsTest.java @@ -2,7 +2,6 @@ package cgeo.geocaching; import static org.assertj.core.api.Assertions.assertThat; -import cgeo.geocaching.connector.gc.GCConstants; import cgeo.geocaching.maps.mapsforge.MapsforgeMapProvider; import cgeo.geocaching.settings.Settings; @@ -21,15 +20,13 @@ public class SettingsTest extends ActivityInstrumentationTestCase2<MainActivity> * this should work fine without an exception (once there was an exception because of the empty map file string) */ public static void testSettingsException() { - final String mapFile = Settings.getMapFile(); // We just want to ensure that it does not throw any exception but we do not know anything about the result - MapsforgeMapProvider.isValidMapFile(mapFile); - assertThat(true).isTrue(); + MapsforgeMapProvider.isValidMapFile(Settings.getMapFile()); } public static void testSettings() { // unfortunately, several other tests depend on being a premium member and will fail if run by a basic member - assertThat(Settings.getGCMemberStatus()).isEqualTo(GCConstants.MEMBER_STATUS_PM); + assertThat(Settings.isGCPremiumMember()).isTrue(); } public static void testDeviceHasNormalLogin() { diff --git a/tests/src/cgeo/geocaching/StaticMapsProviderTest.java b/tests/src/cgeo/geocaching/StaticMapsProviderTest.java index 42ad2c5..02b1d02 100644 --- a/tests/src/cgeo/geocaching/StaticMapsProviderTest.java +++ b/tests/src/cgeo/geocaching/StaticMapsProviderTest.java @@ -4,9 +4,10 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.enumerations.WaypointType; import cgeo.geocaching.files.LocalStorage; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.TestSettings; +import cgeo.geocaching.utils.FileUtils; import cgeo.geocaching.utils.RxUtils; import junit.framework.TestCase; @@ -78,7 +79,7 @@ public class StaticMapsProviderTest extends TestCase { private static void deleteCacheDirectory(String geocode) { File cacheDir = LocalStorage.getStorageDir(geocode); - LocalStorage.deleteDirectory(cacheDir); + FileUtils.deleteDirectory(cacheDir); } } diff --git a/tests/src/cgeo/geocaching/WaypointTest.java b/tests/src/cgeo/geocaching/WaypointTest.java index a3dabbf..9e14146 100644 --- a/tests/src/cgeo/geocaching/WaypointTest.java +++ b/tests/src/cgeo/geocaching/WaypointTest.java @@ -3,7 +3,7 @@ package cgeo.geocaching; import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.test.AndroidTestCase; diff --git a/tests/src/cgeo/geocaching/activity/AbstractEspressoTest.java b/tests/src/cgeo/geocaching/activity/AbstractEspressoTest.java new file mode 100644 index 0000000..0647ec8 --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/AbstractEspressoTest.java @@ -0,0 +1,30 @@ +package cgeo.geocaching.activity; + +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onData; +import static com.google.android.apps.common.testing.ui.espresso.Espresso.openActionBarOverflowOrOptionsMenu; +import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.click; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.startsWith; + +import android.app.Activity; +import android.test.ActivityInstrumentationTestCase2; + +public abstract class AbstractEspressoTest<T extends Activity> extends ActivityInstrumentationTestCase2<T> { + + public AbstractEspressoTest(Class<T> activityClass) { + super(activityClass); + } + + protected final void clickActionBarItem(int labelResourceId) { + onData(hasToString(startsWith(getString(labelResourceId)))).perform(click()); + } + + protected final void openActionBar() { + openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); + } + + protected final String getString(int resId) { + return getActivity().getString(resId); + } + +} diff --git a/tests/src/cgeo/geocaching/activity/logtrackable/AbstractLogTrackableActivityTest.java b/tests/src/cgeo/geocaching/activity/logtrackable/AbstractLogTrackableActivityTest.java new file mode 100644 index 0000000..d93f1ad --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/logtrackable/AbstractLogTrackableActivityTest.java @@ -0,0 +1,31 @@ +package cgeo.geocaching.activity.logtrackable; + +import cgeo.geocaching.DataStore; +import cgeo.geocaching.LogTrackableActivity; +import cgeo.geocaching.Trackable; +import cgeo.geocaching.activity.AbstractEspressoTest; + +public abstract class AbstractLogTrackableActivityTest extends AbstractEspressoTest<LogTrackableActivity> { + + private static Trackable trackable; + + public AbstractLogTrackableActivityTest() { + super(LogTrackableActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + createTrackable(); + setActivityIntent(LogTrackableActivity.getIntent(getInstrumentation().getContext(), trackable)); + getActivity(); + } + + protected static void createTrackable() { + trackable = new Trackable(); + trackable.setName("Test trackable"); + trackable.setGeocode("TB4D09K"); + DataStore.saveTrackable(trackable); + } + +} diff --git a/tests/src/cgeo/geocaching/activity/logtrackable/LogTrackableActivityTest.java b/tests/src/cgeo/geocaching/activity/logtrackable/LogTrackableActivityTest.java new file mode 100644 index 0000000..cb2a209 --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/logtrackable/LogTrackableActivityTest.java @@ -0,0 +1,26 @@ +package cgeo.geocaching.activity.logtrackable; + +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView; +import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.doesNotExist; +import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isDisplayed; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText; + +import cgeo.geocaching.R; + +public class LogTrackableActivityTest extends AbstractLogTrackableActivityTest { + + public void testInsertNameExists() throws Exception { + openActionBar(); + clickActionBarItem(R.string.log_add); + + onView(withText(getString(R.string.init_signature_template_name))).check(matches(isDisplayed())); + } + + public void testInsertNumberNotExists() throws Exception { + openActionBar(); + clickActionBarItem(R.string.log_add); + + onView(withText(getString(R.string.init_signature_template_number))).check(doesNotExist()); + } +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/AbstractAddWaypointActivityTest.java b/tests/src/cgeo/geocaching/activity/waypoint/AbstractAddWaypointActivityTest.java new file mode 100644 index 0000000..7be6150 --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/AbstractAddWaypointActivityTest.java @@ -0,0 +1,12 @@ +package cgeo.geocaching.activity.waypoint; + +import cgeo.geocaching.EditWaypointActivity_; + +public abstract class AbstractAddWaypointActivityTest extends AbstractWaypointActivityTest { + @Override + protected void setUp() throws Exception { + super.setUp(); + setActivityIntent(new EditWaypointActivity_.IntentBuilder_(getInstrumentation().getContext()).geocode(getCache().getGeocode()).get()); + getActivity(); + } +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/AbstractEditWaypointActivityTest.java b/tests/src/cgeo/geocaching/activity/waypoint/AbstractEditWaypointActivityTest.java new file mode 100644 index 0000000..bf8224a --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/AbstractEditWaypointActivityTest.java @@ -0,0 +1,28 @@ +package cgeo.geocaching.activity.waypoint; + +import cgeo.geocaching.EditWaypointActivity_; +import cgeo.geocaching.Waypoint; +import cgeo.geocaching.enumerations.WaypointType; + +public abstract class AbstractEditWaypointActivityTest extends AbstractWaypointActivityTest { + private Waypoint waypoint; + + @Override + protected void setUp() throws Exception { + super.setUp(); + createWaypoint(); + getCache().addOrChangeWaypoint(waypoint, true); + final int waypointId = getCache().getWaypoints().get(0).getId(); + setActivityIntent(new EditWaypointActivity_.IntentBuilder_(getInstrumentation().getContext()).geocode(getCache().getGeocode()).waypointId(waypointId).get()); + getActivity(); + } + + private void createWaypoint() { + waypoint = new Waypoint("Test waypoint", WaypointType.PUZZLE, true); + waypoint.setNote("Test note"); + } + + protected final Waypoint getWaypoint() { + return waypoint; + } +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/AbstractWaypointActivityTest.java b/tests/src/cgeo/geocaching/activity/waypoint/AbstractWaypointActivityTest.java new file mode 100644 index 0000000..36c4302 --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/AbstractWaypointActivityTest.java @@ -0,0 +1,52 @@ +package cgeo.geocaching.activity.waypoint; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.DataStore; +import cgeo.geocaching.EditWaypointActivity_; +import cgeo.geocaching.Geocache; +import cgeo.geocaching.activity.AbstractEspressoTest; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.enumerations.LoadFlags; +import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; + +import java.util.Collections; + +public abstract class AbstractWaypointActivityTest extends AbstractEspressoTest<EditWaypointActivity_> { + + private Geocache cache; + + public AbstractWaypointActivityTest() { + super(EditWaypointActivity_.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + cache = createTestCache(); + DataStore.saveCache(cache, Collections.singleton(SaveFlag.CACHE)); + } + + @Override + protected void tearDown() throws Exception { + removeTestCache(); + super.tearDown(); + } + + protected final Geocache getCache() { + return cache; + } + + private void removeTestCache() { + DataStore.removeCache(cache.getGeocode(), LoadFlags.REMOVE_ALL); + assertThat(DataStore.loadCache(cache.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB)).isNull(); + } + + @SuppressWarnings("static-method") + protected Geocache createTestCache() { + Geocache testCache = new Geocache(); + testCache.setGeocode("TEST"); + testCache.setType(CacheType.TRADITIONAL); + return testCache; + } +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointActivityTest.java b/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointActivityTest.java new file mode 100644 index 0000000..853054a --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointActivityTest.java @@ -0,0 +1,62 @@ +package cgeo.geocaching.activity.waypoint; + +import cgeo.geocaching.R; +import cgeo.geocaching.enumerations.WaypointType; + +import com.google.android.apps.common.testing.ui.espresso.action.ViewActions; + +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onData; +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView; + +import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches; + +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isClickable; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isDisplayed; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isNotChecked; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withChild; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withId; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText; + +import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.click; + +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.startsWith; + +public class AddWaypointActivityTest extends AbstractAddWaypointActivityTest { + + public static void testAddWayPointHasTypeSelection() { + onView(withId(R.id.type)).check(matches(isDisplayed())); + } + + public static void testDefaultWaypointTypeForTraditional() { + onView(withId(R.id.type)).check(matches(withChild(withText(WaypointType.WAYPOINT.getL10n())))); + onView(withId(R.id.name)).check(matches(withText(WaypointType.WAYPOINT.getL10n() + " 1"))); + } + + public static void testFieldsAreEmpty() { + onView(withId(R.id.note)).check(matches(withText(""))); + onView(withId(R.id.bearing)).check(matches(withText(""))); + onView(withId(R.id.distance)).check(matches(withText(""))); + } + + public static void testNewWaypointNotVisited() { + onView(withId(R.id.wpt_visited_checkbox)).check(matches(isNotChecked())); + } + + public static void testSwitchingWaypointTypeChangesWaypointName() { + WaypointType waypointType = WaypointType.FINAL; + + // verify we don't have a final type yet + onView(withId(R.id.name)).check(matches(not(withText(waypointType.getL10n())))); + + // open type selector + onView(withId(R.id.type)).perform(ViewActions.click()); + + // select final type + onData(hasToString(startsWith(waypointType.getL10n()))).inAdapterView(isClickable()).perform(click()); + + // verify changed name + onView(withId(R.id.name)).check(matches(withText(waypointType.getL10n()))); + } +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointMultiTest.java b/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointMultiTest.java new file mode 100644 index 0000000..c66c8de --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointMultiTest.java @@ -0,0 +1,34 @@ +package cgeo.geocaching.activity.waypoint; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.enumerations.WaypointType; + +import com.google.android.apps.common.testing.ui.espresso.ViewInteraction; + +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView; + +import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches; + +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isDisplayed; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withChild; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withId; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText; + +public class AddWaypointMultiTest extends AbstractAddWaypointActivityTest { + + @Override + protected Geocache createTestCache() { + final Geocache cache = super.createTestCache(); + cache.setType(CacheType.MULTI); + return cache; + } + + public static void testMysteryDefaultWaypointFinal() { + final ViewInteraction waypointTypeSelector = onView(withId(R.id.type)); + waypointTypeSelector.check(matches(isDisplayed())); + waypointTypeSelector.check(matches(withChild(withText(WaypointType.STAGE.getL10n())))); + } + +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointMysteryTest.java b/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointMysteryTest.java new file mode 100644 index 0000000..810aa25 --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/AddWaypointMysteryTest.java @@ -0,0 +1,32 @@ +package cgeo.geocaching.activity.waypoint; + +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView; +import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isDisplayed; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withChild; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withId; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.enumerations.WaypointType; + +import com.google.android.apps.common.testing.ui.espresso.ViewInteraction; + +public class AddWaypointMysteryTest extends AbstractAddWaypointActivityTest { + + @Override + protected Geocache createTestCache() { + final Geocache cache = super.createTestCache(); + cache.setType(CacheType.MYSTERY); + return cache; + } + + public static void testMysteryDefaultWaypointFinal() { + final ViewInteraction waypointTypeSelector = onView(withId(R.id.type)); + waypointTypeSelector.check(matches(isDisplayed())); + waypointTypeSelector.check(matches(withChild(withText(WaypointType.FINAL.getL10n())))); + } + +} diff --git a/tests/src/cgeo/geocaching/activity/waypoint/EditWaypointActivityTest.java b/tests/src/cgeo/geocaching/activity/waypoint/EditWaypointActivityTest.java new file mode 100644 index 0000000..d419555 --- /dev/null +++ b/tests/src/cgeo/geocaching/activity/waypoint/EditWaypointActivityTest.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.activity.waypoint; + +import cgeo.geocaching.R; + +import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView; + +import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches; + +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withChild; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withId; +import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EditWaypointActivityTest extends AbstractEditWaypointActivityTest { + + public void testFieldsAreNotEmpty() { + String name = getWaypoint().getName(); + assertThat(name).isNotEmpty(); + onView(withId(R.id.name)).check(matches(withText(name))); + + final String note = getWaypoint().getNote(); + assertThat(note).isNotEmpty(); + onView(withId(R.id.note)).check(matches(withText(note))); + + onView(withId(R.id.type)).check(matches(withChild(withText(getWaypoint().getWaypointType().getL10n())))); + } + +} diff --git a/tests/src/cgeo/geocaching/connector/WaymarkingConnectorTest.java b/tests/src/cgeo/geocaching/connector/WaymarkingConnectorTest.java new file mode 100644 index 0000000..c4eacc5 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/WaymarkingConnectorTest.java @@ -0,0 +1,21 @@ +package cgeo.geocaching.connector; + +import static org.assertj.core.api.Assertions.assertThat; +import junit.framework.TestCase; + +public class WaymarkingConnectorTest extends TestCase { + + public static void testGetGeocodeFromUrl() { + assertThat(ConnectorFactory.getGeocodeFromURL("http://coord.info/WM1234")).isEqualTo("WM1234"); + assertThat(ConnectorFactory.getGeocodeFromURL("http://www.waymarking.com/waymarks/WMNCDT_American_Legion_Flagpole_1983_University_of_Oregon")).isEqualTo("WMNCDT"); + + final IConnector wmConnector = ConnectorFactory.getConnector("WM1234"); + assertThat(wmConnector).isNotNull(); + + assertThat(wmConnector.getGeocodeFromUrl("http://coord.info/WM1234")).isEqualTo("WM1234"); + assertThat(wmConnector.getGeocodeFromUrl("http://www.waymarking.com/waymarks/WMNCDT_American_Legion_Flagpole_1983_University_of_Oregon")).isEqualTo("WMNCDT"); + + assertThat(wmConnector.getGeocodeFromUrl("http://coord.info/GC12ABC")).isNull(); + assertThat(wmConnector.getGeocodeFromUrl("http://coord.info/TB1234")).isNull(); + } +} diff --git a/tests/src/cgeo/geocaching/connector/ec/ECConnectorTest.java b/tests/src/cgeo/geocaching/connector/ec/ECConnectorTest.java index aa6a185..f4073a9 100644 --- a/tests/src/cgeo/geocaching/connector/ec/ECConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/ec/ECConnectorTest.java @@ -32,4 +32,8 @@ public class ECConnectorTest extends TestCase { return geocache; } + public static void testGetGeocodeFromUrl() throws Exception { + assertThat(ECConnector.getInstance().getGeocodeFromUrl("http://extremcaching.com/index.php/output-2/738")).isEqualTo("EC738"); + } + } diff --git a/tests/src/cgeo/geocaching/connector/gc/AutoZoomTest.java b/tests/src/cgeo/geocaching/connector/gc/AutoZoomTest.java index 63924ab..f7dbe72 100644 --- a/tests/src/cgeo/geocaching/connector/gc/AutoZoomTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/AutoZoomTest.java @@ -2,8 +2,8 @@ package cgeo.geocaching.connector.gc; import static org.assertj.core.api.Assertions.assertThat; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import java.util.Set; diff --git a/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java index 811c0e4..30a9af9 100644 --- a/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java @@ -6,8 +6,8 @@ import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.trackable.TravelBugConnector; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.geopoint.Geopoint; -import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.TestSettings; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; @@ -82,7 +82,7 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase { assertTileAt(7536, 4915, new Tile(new Geopoint("S 33° 50.326 E 151° 12.426"), 13)); } - private static void assertTileAt(int x, int y, final Tile tile) { + private static void assertTileAt(final int x, final int y, final Tile tile) { assertThat(tile.getX()).isEqualTo(x); assertThat(tile.getY()).isEqualTo(y); } @@ -96,5 +96,6 @@ public class GCConnectorTest extends AbstractResourceInstrumentationTestCase { assertThat(GCConnector.getInstance().getGeocodeFromUrl("http://coord.info/TB1234")).isNull(); assertThat(GCConnector.getInstance().getGeocodeFromUrl("http://www.coord.info/TB1234")).isNull(); + assertThat(GCConnector.getInstance().getGeocodeFromUrl("http://www.coord.info/WM1234")).isNull(); } } diff --git a/tests/src/cgeo/geocaching/connector/gc/GCConstantsTest.java b/tests/src/cgeo/geocaching/connector/gc/GCConstantsTest.java index ef50709..57e494a 100644 --- a/tests/src/cgeo/geocaching/connector/gc/GCConstantsTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCConstantsTest.java @@ -11,8 +11,8 @@ import android.text.Html; public class GCConstantsTest extends AndroidTestCase { // adapt the following after downloading new mock html files - public static final String MOCK_LOGIN_NAME = "JoSaMaJa"; - public static final int MOCK_CACHES_FOUND = 484; + public static final String MOCK_LOGIN_NAME = "Bananeweizen"; + public static final int MOCK_CACHES_FOUND = 743; public static void testLocation() { // GC37GFJ @@ -26,15 +26,15 @@ public class GCConstantsTest extends AndroidTestCase { } public static void testCacheCount() { - assertCacheCount(1510, "<strong style=\"display:block\"> 1.510 Caches Found</strong>"); - assertCacheCount(1510, "<strong style=\"display:block\"> 1,510 Caches Found</strong>"); + assertCacheCount(1510, "<span>1.510 Finds</span>"); + assertCacheCount(1510, "<span>1,510 Finds</span>"); assertCacheCount(MOCK_CACHES_FOUND, MockedCache.readCachePage("GC2CJPF")); } private static void assertCacheCount(final int count, final String html) { try { assertEquals(count, Integer.parseInt(TextUtils.getMatch(html, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""))); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { fail(); } } diff --git a/tests/src/cgeo/geocaching/connector/gc/GCLoginTest.java b/tests/src/cgeo/geocaching/connector/gc/GCLoginTest.java new file mode 100644 index 0000000..6022e59 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/gc/GCLoginTest.java @@ -0,0 +1,32 @@ +package cgeo.geocaching.connector.gc; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.enumerations.StatusCode; + +import org.apache.commons.lang3.StringUtils; + +import android.test.suitebuilder.annotation.Suppress; + +import junit.framework.TestCase; + +public class GCLoginTest extends TestCase { + + final GCLogin instance = GCLogin.getInstance(); + + @Override + protected void setUp() throws Exception { + super.setUp(); + assertThat(instance.login()).isEqualTo(StatusCode.NO_ERROR); + } + + public static void testHomeLocation() { + assertThat(StringUtils.isNotBlank(GCLogin.retrieveHomeLocation())).isTrue(); + } + + @Suppress // It currently fails on CI + public void testAvatar() { + assertThat(instance.downloadAvatar()).isNotNull(); + } + +} diff --git a/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java index be96cf3..81838e6 100644 --- a/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/GCParserTest.java @@ -11,7 +11,7 @@ import cgeo.geocaching.Waypoint; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; @@ -57,7 +57,7 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { assertThat(result.getCount()).isEqualTo(1); final Geocache cache = result.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); assertThat(cache).isNotNull(); - assert (cache != null); // eclipse bug + assert cache != null; // eclipse bug assertThat(cache.getName()).isEqualTo(cacheName); } @@ -71,7 +71,7 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { assertThat(spoiler.getDescription()).as("First spoiler image description").isNull(); } - private static Geocache createCache(int index) { + private static Geocache createCache(final int index) { final MockedCache mockedCache = RegExPerformanceTest.MOCKED_CACHES.get(index); // to get the same results we have to use the date format used when the mocked data was created final String oldCustomDate = Settings.getGcCustomDate(); @@ -93,19 +93,25 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { } /** - * Test {@link GCParser#parseCacheFromText(String, int, CancellableHandler)} with "mocked" data + * Test {@link GCParser#parseAndSaveCacheFromText(String, CancellableHandler)} with "mocked" data * */ @MediumTest public static void testParseCacheFromTextWithMockedData() { final String gcCustomDate = Settings.getGcCustomDate(); try { - for (MockedCache mockedCache : RegExPerformanceTest.MOCKED_CACHES) { + for (final MockedCache mockedCache : RegExPerformanceTest.MOCKED_CACHES) { // to get the same results we have to use the date format used when the mocked data was created Settings.setGcCustomDate(MockedCache.getDateFormat()); - SearchResult searchResult = GCParser.parseAndSaveCacheFromText(mockedCache.getData(), null); - Geocache parsedCache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + final SearchResult searchResult = GCParser.parseAndSaveCacheFromText(mockedCache.getData(), null); + final Geocache parsedCache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB); + assertThat(parsedCache).isNotNull(); + assert parsedCache != null; // To keep editors happy assertThat(StringUtils.isNotBlank(mockedCache.getMockedDataUser())).isTrue(); + // Workaround for issue #3777 + if (mockedCache.getGeocode().equals("GC3XX5J") && Settings.getUsername().equals("mucek4")) { + parsedCache.setFound(true); + } Compare.assertCompareCaches(mockedCache, parsedCache, true); } } finally { @@ -160,7 +166,7 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { final String page = GCParser.requestHtmlPage(cache.getGeocode(), null, "n"); final Geocache cache2 = GCParser.parseAndSaveCacheFromText(page, null).getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY); assertThat(cache2).isNotNull(); - assert (cache2 != null); // eclipse bug + assert cache2 != null; // eclipse bug assertThat(cache2.hasUserModifiedCoords()).isTrue(); assertEquals(new Geopoint("N51 21.544", "E07 02.566"), cache2.getCoords()); // delete coordinates @@ -169,11 +175,11 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { final String page2 = GCParser.requestHtmlPage(cache.getGeocode(), null, "n"); final Geocache cache3 = GCParser.parseAndSaveCacheFromText(page2, null).getFirstCacheFromResult(LoadFlags.LOAD_CACHE_ONLY); assertThat(cache3).isNotNull(); - assert (cache3 != null); // eclipse bug + assert cache3 != null; // eclipse bug assertThat(cache3.hasUserModifiedCoords()).isFalse(); } - private static void assertWaypointsFromNote(final Geocache cache, Geopoint[] expected, String note) { + private static void assertWaypointsFromNote(final Geocache cache, final Geopoint[] expected, final String note) { cache.setPersonalNote(note); cache.setWaypoints(new ArrayList<Waypoint>(), false); cache.parseWaypointsFromNote(); @@ -208,7 +214,7 @@ public class GCParserTest extends AbstractResourceInstrumentationTestCase { assertThat(waypoints.get(2).getWaypointType()).isEqualTo(WaypointType.WAYPOINT); } - private Geocache parseCache(int resourceId) { + private Geocache parseCache(final int resourceId) { final String page = getFileContent(resourceId); final SearchResult result = GCParser.parseAndSaveCacheFromText(page, null); assertThat(result).isNotNull(); diff --git a/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java b/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java index 89eada3..bf185b3 100644 --- a/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java +++ b/tests/src/cgeo/geocaching/connector/gc/TrackablesTest.java @@ -18,6 +18,7 @@ public class TrackablesTest extends AbstractResourceInstrumentationTestCase { public void testLogPageWithTrackables() { final List<TrackableLog> tbLogs = GCParser.parseTrackableLog(getFileContent(R.raw.log_with_2tb)); assertThat(tbLogs).isNotNull(); + assert tbLogs != null; assertThat(tbLogs).hasSize(2); final TrackableLog log = tbLogs.get(0); assertThat(log.name).isEqualTo("Steffen's Kaiserwagen"); diff --git a/tests/src/cgeo/geocaching/connector/oc/OCCZConnectorTest.java b/tests/src/cgeo/geocaching/connector/oc/OCCZConnectorTest.java new file mode 100644 index 0000000..52fc5c8 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/oc/OCCZConnectorTest.java @@ -0,0 +1,14 @@ +package cgeo.geocaching.connector.oc; + +import static org.assertj.core.api.Assertions.assertThat; +import junit.framework.TestCase; + +public class OCCZConnectorTest extends TestCase { + + public static void testGetGeocodeFromUrl() throws Exception { + final OCCZConnector connector = new OCCZConnector(); + assertThat(connector.getGeocodeFromUrl("http://opencaching.cz/viewcache.php?cacheid=610")).isEqualTo("OZ0262"); + assertThat(connector.getGeocodeFromUrl("http://www.opencaching.de/viewcache.php?cacheid=151223")).isNull(); + } + +} diff --git a/tests/src/cgeo/geocaching/connector/oc/OCConnectorTest.java b/tests/src/cgeo/geocaching/connector/oc/OCConnectorTest.java index 0aad3aa..697b8d8 100644 --- a/tests/src/cgeo/geocaching/connector/oc/OCConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/oc/OCConnectorTest.java @@ -24,4 +24,15 @@ public class OCConnectorTest extends TestCase { return ocConnector; } + public static void testGetGeocodeFromUrlDe() throws Exception { + final IConnector connector = ConnectorFactory.getConnector("OC0028"); + assertThat(connector.getGeocodeFromUrl("http://opencaching.de/OC0028")).isEqualTo("OC0028"); + assertThat(connector.getGeocodeFromUrl("http://www.opencaching.de/OC0028")).isEqualTo("OC0028"); + } + + public static void testGetGeocodeFromUrlUs() throws Exception { + final IConnector connector = ConnectorFactory.getConnector("OU07A0"); + assertThat(connector.getGeocodeFromUrl("http://www.opencaching.us/viewcache.php?wp=OU07A0")).isEqualTo("OU07A0"); + } + } diff --git a/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java b/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java index 20a51b8..22b2dbe 100644 --- a/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java +++ b/tests/src/cgeo/geocaching/connector/oc/OkapiClientTest.java @@ -19,6 +19,7 @@ public class OkapiClientTest extends CGeoTestCase { assertThat(cache.isDetailed()).isTrue(); // cache should be stored to DB (to listID 0) when loaded above cache = DataStore.loadCache(geoCode, LoadFlags.LOAD_ALL_DB_ONLY); + assert cache != null; assertThat(cache).isNotNull(); assertThat(cache.getGeocode()).isEqualTo(geoCode); assertThat(cache.getName()).isEqualTo("Oshkosh Municipal Tank"); @@ -29,7 +30,7 @@ public class OkapiClientTest extends CGeoTestCase { public static void testOCSearchMustWorkWithoutOAuthAccessTokens() { final String geoCode = "OC1234"; - Geocache cache = OkapiClient.getCache(geoCode); + final Geocache cache = OkapiClient.getCache(geoCode); assertThat(cache).overridingErrorMessage("You must have a valid OKAPI key installed for running this test (but you do not need to set credentials in the app).").isNotNull(); assertThat(cache.getName()).isEqualTo("Wupper-Schein"); } @@ -41,6 +42,7 @@ public class OkapiClientTest extends CGeoTestCase { assertThat(cache).as("Cache from OKAPI").isNotNull(); // cache should be stored to DB (to listID 0) when loaded above cache = DataStore.loadCache(geoCode, LoadFlags.LOAD_ALL_DB_ONLY); + assert cache != null; assertThat(cache).isNotNull(); assertThat(cache.getWaypoints()).hasSize(3); @@ -53,9 +55,16 @@ public class OkapiClientTest extends CGeoTestCase { final String geoCode = "OC6465"; removeCacheCompletely(geoCode); - Geocache cache = OkapiClient.getCache(geoCode); + final Geocache cache = OkapiClient.getCache(geoCode); assertThat(cache).as("Cache from OKAPI").isNotNull(); assertThat(cache.getLogCounts().get(LogType.WILL_ATTEND)).isGreaterThan(0); } + public static void testGetAllLogs() { + final String geoCode = "OC10CB8"; + final Geocache cache = OkapiClient.getCache(geoCode); + final int defaultLogCount = 10; + assertThat(cache.getLogs().size()).isGreaterThan(defaultLogCount); + } + } diff --git a/tests/src/cgeo/geocaching/connector/ox/OXConnectorTest.java b/tests/src/cgeo/geocaching/connector/ox/OXConnectorTest.java index 5433387..11f2d66 100644 --- a/tests/src/cgeo/geocaching/connector/ox/OXConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/ox/OXConnectorTest.java @@ -14,4 +14,10 @@ public class OXConnectorTest extends TestCase { assertThat(oxConnector.canHandle("OX_")).isFalse(); } + public static void testGetGeocodeFromUrl() { + final OXConnector connector = new OXConnector(); + assertThat(connector.getGeocodeFromUrl("http://www.opencaching.com/de/#!geocache/OX1R421")).isEqualTo("OX1R421"); + assertThat(connector.getGeocodeFromUrl("http://www.opencaching.com/#!geocache/OX1R421")).isEqualTo("OX1R421"); + } + } diff --git a/tests/src/cgeo/geocaching/connector/trackable/SwaggieConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/SwaggieConnectorTest.java new file mode 100644 index 0000000..54c3319 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/trackable/SwaggieConnectorTest.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.connector.trackable; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.Trackable; + +import junit.framework.TestCase; + +public class SwaggieConnectorTest extends TestCase { + + public static void testCanHandleTrackable() { + assertThat(new SwaggieConnector().canHandleTrackable("SW0001")).isTrue(); + assertThat(new SwaggieConnector().canHandleTrackable("SWABCD")).isFalse(); + assertThat(new SwaggieConnector().canHandleTrackable("GK82A2")).isFalse(); + assertThat(new SwaggieConnector().canHandleTrackable("TB1234")).isFalse(); + assertThat(new SwaggieConnector().canHandleTrackable("UNKNOWN")).isFalse(); + } + + public static void testGetTrackableCodeFromUrl() throws Exception { + assertThat(new SwaggieConnector().getTrackableCodeFromUrl("http://geocaching.com.au/swaggie/sw0017")).isEqualTo("SW0017"); + } + + public static void testGetUrl() throws Exception { + final Trackable trackable = new Trackable(); + trackable.setGeocode("SW0017"); + assertThat(new SwaggieConnector().getUrl(trackable)).isEqualTo("http://geocaching.com.au/swaggie/SW0017"); + } + +} diff --git a/tests/src/cgeo/geocaching/connector/trackable/SwaggieParserTest.java b/tests/src/cgeo/geocaching/connector/trackable/SwaggieParserTest.java new file mode 100644 index 0000000..2661fb3 --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/trackable/SwaggieParserTest.java @@ -0,0 +1,34 @@ +package cgeo.geocaching.connector.trackable; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.Trackable; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.network.Network; + +import junit.framework.TestCase; + +public class SwaggieParserTest extends TestCase { + + public static void testParse() { + final Trackable trackableIn = new Trackable(); + trackableIn.setGeocode("SW0017"); + + final String trackableUrl = ConnectorFactory.getTrackableConnector(trackableIn.getGeocode()).getUrl(trackableIn); + assertThat(trackableUrl).isNotNull(); + + final String page = Network.getResponseData(Network.getRequest(trackableUrl)); + assertThat(page).isNotNull(); + + assert page != null; + final Trackable trackable = SwaggieParser.parse(page); + assertThat(trackable).isNotNull(); + assert trackable != null; + + assertThat(trackable.getName()).isEqualTo("Law and Order 1"); + assertThat(trackable.getGeocode()).isEqualTo("SW0017"); + assertThat(trackable.getDetails()).isEqualTo("A mini CD that may or may not contain a DivX .AVI of the Law and Order: CSI episode that features geocaching as part of the storyline."); + assertThat(trackable.getType()).isEqualTo("Swaggie"); + assertThat(trackable.getOwner()).isEqualTo("Bear_Left"); + } +} diff --git a/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java index 8d80822..7123e87 100644 --- a/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java +++ b/tests/src/cgeo/geocaching/connector/trackable/TravelBugConnectorTest.java @@ -26,14 +26,16 @@ public class TravelBugConnectorTest extends TestCase { } public static void testOnlineSearchBySecretCode() { - Trackable trackable = getConnector().searchTrackable("GST9HV", null, null); + final Trackable trackable = getConnector().searchTrackable("GST9HV", null, null); assertThat(trackable).isNotNull(); + assert trackable != null; assertThat(trackable.getName()).isEqualTo("Deutschland"); } public static void testOnlineSearchByPublicCode() { - Trackable trackable = getConnector().searchTrackable("TB4JD36", null, null); + final Trackable trackable = getConnector().searchTrackable("TB4JD36", null, null); assertThat(trackable).isNotNull(); + assert trackable != null; assertThat(trackable.getName()).isEqualTo("Mein Kilometerzähler"); } diff --git a/tests/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnectorTest.java b/tests/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnectorTest.java new file mode 100644 index 0000000..ded0a1a --- /dev/null +++ b/tests/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnectorTest.java @@ -0,0 +1,44 @@ +package cgeo.geocaching.connector.trackable; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.Trackable; + +import junit.framework.TestCase; + +public class UnknownTrackableConnectorTest extends TestCase { + + private static UnknownTrackableConnector getConnector() { + return new UnknownTrackableConnector(); + } + + public static void testCanHandleTrackable() throws Exception { + assertThat(getConnector().canHandleTrackable("TB1234")).isFalse(); + } + + public static void testGetUrl() throws Exception { + try { + getConnector().getUrl(new Trackable()); + fail("IllegalStateException expected"); + } catch (final IllegalStateException e) { + // empty + } + } + + public static void testSearchTrackable() throws Exception { + assertThat(getConnector().searchTrackable("TB1234", null, null)).isNull(); + } + + public static void testIsLoggable() throws Exception { + assertThat(getConnector().isLoggable()).isFalse(); + } + + public static void testGetTrackableCodeFromUrl() throws Exception { + assertThat(getConnector().getTrackableCodeFromUrl("http://www.sometrackable.com/1234")).isNull(); + } + + public static void testGetUserActions() throws Exception { + assertThat(getConnector().getUserActions()).isEmpty(); + } + +} diff --git a/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java b/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java index a8a9ced..f9e25bf 100644 --- a/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java +++ b/tests/src/cgeo/geocaching/enumerations/CacheAttributeTest.java @@ -2,6 +2,8 @@ package cgeo.geocaching.enumerations; import static org.assertj.core.api.Assertions.assertThat; +import org.apache.commons.lang3.StringUtils; + import android.test.AndroidTestCase; public class CacheAttributeTest extends AndroidTestCase { @@ -16,8 +18,7 @@ public class CacheAttributeTest extends AndroidTestCase { public static void testIds() { for (CacheAttribute attribute : CacheAttribute.values()) { if (attribute != CacheAttribute.UNKNOWN) { - assertThat(attribute.rawName != null).isTrue(); - assertThat(attribute.rawName.length() > 0).isTrue(); + assertThat(StringUtils.isNotEmpty(attribute.rawName)).isTrue(); assertThat(attribute.drawableId != 0).isTrue(); assertThat(attribute.stringIdYes != 0).isTrue(); assertThat(attribute.stringIdNo != 0).isTrue(); @@ -43,9 +44,8 @@ public class CacheAttributeTest extends AndroidTestCase { } public static void testIsEnabled() { - final CacheAttribute attribute = CacheAttribute.HIKING; - final String hiking_yes = attribute.getAttributeName(true); - final String hiking_no = attribute.getAttributeName(false); + final String hiking_yes = "hiking_yes"; + final String hiking_no = "hiking_no"; assertThat(CacheAttribute.isEnabled(hiking_yes)).isTrue(); assertThat(CacheAttribute.isEnabled(hiking_no)).isFalse(); } diff --git a/tests/src/cgeo/geocaching/export/ExportTest.java b/tests/src/cgeo/geocaching/export/ExportTest.java index 848a1f7..21c45a0 100644 --- a/tests/src/cgeo/geocaching/export/ExportTest.java +++ b/tests/src/cgeo/geocaching/export/ExportTest.java @@ -6,12 +6,14 @@ import cgeo.CGeoTestCase; import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; +import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.FileUtils; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -23,21 +25,38 @@ public class ExportTest extends CGeoTestCase { final Geocache cache = new Geocache(); cache.setGeocode("GCX1234"); final LogEntry log = new LogEntry(1353244820000L, LogType.FOUND_IT, "Hidden in a tree"); - FieldNotes fieldNotes = new FieldNotes(); + final FieldNotes fieldNotes = new FieldNotes(); fieldNotes.add(cache, log); assertEquals("Non matching export " + fieldNotes.getContent(), "GCX1234,2012-11-18T13:20:20Z,Found it,\"Hidden in a tree\"\n", fieldNotes.getContent()); } - public static void testGpxExportSmilies() throws InterruptedException, ExecutionException { + public static void testGpxExportSmilies() throws InterruptedException, ExecutionException, IOException { final Geocache cache = new Geocache(); cache.setGeocode("GCX1234"); cache.setCoords(new Geopoint("N 49 44.000 E 8 37.000")); final LogEntry log = new LogEntry(1353244820000L, LogType.FOUND_IT, "Smile: \ud83d\ude0a"); DataStore.saveCache(cache, LoadFlags.SAVE_ALL); - DataStore.saveLogsWithoutTransaction(cache.getGeocode(), Collections.singletonList(log)); - ArrayList<Geocache> exportList = new ArrayList<Geocache>(); - exportList.add(cache); - GpxExportTester gpxExport = new GpxExportTester(); + DataStore.saveLogs(cache.getGeocode(), Collections.singletonList(log)); + assertCanExport(cache); + } + + public static void testGpxExportUnknownConnector() throws InterruptedException, ExecutionException, IOException { + final Geocache cache = new Geocache(); + cache.setGeocode("ABC123"); + cache.setCoords(new Geopoint("N 49 44.000 E 8 37.000")); + DataStore.saveCache(cache, LoadFlags.SAVE_ALL); + + assertThat(ConnectorFactory.getConnector(cache).getName()).isEqualTo("Unknown caches"); + assertCanExport(cache); + } + + private static void assertCanExport(final Geocache cache) throws InterruptedException, ExecutionException, IOException { + // enforce storing in database, as GPX will not take information from cache + cache.setDetailed(true); + DataStore.saveCache(cache, LoadFlags.SAVE_ALL); + + final List<Geocache> exportList = Collections.singletonList(cache); + final GpxExportTester gpxExport = new GpxExportTester(); File result = null; try { result = gpxExport.testExportSync(exportList); @@ -47,13 +66,23 @@ public class ExportTest extends CGeoTestCase { assertThat(result).isNotNull(); + // make sure we actually exported waypoints + final String gpx = org.apache.commons.io.FileUtils.readFileToString(result); + assertThat(gpx).contains("<wpt"); + assertThat(gpx).contains(cache.getGeocode()); + if (cache.getUrl() != null) { + assertThat(gpx).contains("<url>"); + } else { + assertThat(gpx).doesNotContain("<url>"); + } + FileUtils.deleteIgnoringFailure(result); } private static class GpxExportTester extends GpxExport { - public File testExportSync(List<Geocache> caches) throws InterruptedException, ExecutionException { - final ArrayList<String> geocodes = new ArrayList<String>(caches.size()); + public File testExportSync(final List<Geocache> caches) throws InterruptedException, ExecutionException { + final ArrayList<String> geocodes = new ArrayList<>(caches.size()); for (final Geocache cache : caches) { geocodes.add(cache.getGeocode()); } diff --git a/tests/src/cgeo/geocaching/export/GpxSerializerTest.java b/tests/src/cgeo/geocaching/export/GpxSerializerTest.java index 809c121..b20b066 100644 --- a/tests/src/cgeo/geocaching/export/GpxSerializerTest.java +++ b/tests/src/cgeo/geocaching/export/GpxSerializerTest.java @@ -38,13 +38,13 @@ public class GpxSerializerTest extends AbstractResourceInstrumentationTestCase { final AtomicReference<Integer> importedCount = new AtomicReference<Integer>(0); final StringWriter writer = new StringWriter(); - Geocache cache = loadCacheFromResource(R.raw.gc1bkp3_gpx101); + final Geocache cache = loadCacheFromResource(R.raw.gc1bkp3_gpx101); assertThat(cache).isNotNull(); new GpxSerializer().writeGPX(Collections.singletonList("GC1BKP3"), writer, new GpxSerializer.ProgressListener() { @Override - public void publishProgress(int countExported) { + public void publishProgress(final int countExported) { importedCount.set(countExported); } }); @@ -54,8 +54,6 @@ public class GpxSerializerTest extends AbstractResourceInstrumentationTestCase { /** * This test verifies that a loop of import, export, import leads to the same cache information. * - * @throws IOException - * @throws ParserException */ public void testStableExportImportExport() throws IOException, ParserException { final String geocode = "GC1BKP3"; @@ -67,10 +65,10 @@ public class GpxSerializerTest extends AbstractResourceInstrumentationTestCase { assertThat(gpxFirst.length() > 0).isTrue(); - final GPX10Parser parser = new GPX10Parser(StoredList.TEMPORARY_LIST_ID); + final GPX10Parser parser = new GPX10Parser(StoredList.TEMPORARY_LIST.id); final InputStream stream = new ByteArrayInputStream(gpxFirst.getBytes(CharEncoding.UTF_8)); - Collection<Geocache> caches = parser.parse(stream, null); + final Collection<Geocache> caches = parser.parse(stream, null); assertThat(caches).isNotNull(); assertThat(caches).hasSize(1); @@ -78,43 +76,43 @@ public class GpxSerializerTest extends AbstractResourceInstrumentationTestCase { assertThat(replaceLogIds(gpxSecond)).isEqualTo(replaceLogIds(gpxFirst)); } - private static String replaceLogIds(String gpx) { + private static String replaceLogIds(final String gpx) { return gpx.replaceAll("log id=\"\\d*\"", ""); } - private static String getGPXFromCache(String geocode) throws IOException { + private static String getGPXFromCache(final String geocode) throws IOException { final StringWriter writer = new StringWriter(); new GpxSerializer().writeGPX(Collections.singletonList(geocode), writer, null); return writer.toString(); } public static void testStateFromStateCountry() throws Exception { - Geocache cache = withLocation("state, country"); + final Geocache cache = withLocation("state, country"); assertThat(GpxSerializer.getState(cache)).isEqualTo("state"); } public static void testCountryFromStateCountry() throws Exception { - Geocache cache = withLocation("state, country"); + final Geocache cache = withLocation("state, country"); assertThat(GpxSerializer.getCountry(cache)).isEqualTo("country"); } public static void testCountryFromCountryOnly() throws Exception { - Geocache cache = withLocation("somewhere"); + final Geocache cache = withLocation("somewhere"); assertThat(GpxSerializer.getCountry(cache)).isEqualTo("somewhere"); } public static void testStateFromCountryOnly() throws Exception { - Geocache cache = withLocation("somewhere"); + final Geocache cache = withLocation("somewhere"); assertThat(GpxSerializer.getState(cache)).isEmpty(); } public static void testCountryFromExternalCommaString() throws Exception { - Geocache cache = withLocation("first,second"); // this was not created by c:geo, therefore don't split it + final Geocache cache = withLocation("first,second"); // this was not created by c:geo, therefore don't split it assertThat(GpxSerializer.getState(cache)).isEmpty(); } private static Geocache withLocation(final String location) { - Geocache cache = new Geocache(); + final Geocache cache = new Geocache(); cache.setLocation(location); return cache; } diff --git a/tests/src/cgeo/geocaching/files/GPXImporterTest.java b/tests/src/cgeo/geocaching/files/GPXImporterTest.java index f72cf4a..86fa90d 100644 --- a/tests/src/cgeo/geocaching/files/GPXImporterTest.java +++ b/tests/src/cgeo/geocaching/files/GPXImporterTest.java @@ -78,6 +78,8 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { final SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj; assertThat(new ArrayList<String>(search.getGeocodes())).isEqualTo(Collections.singletonList(geocode)); final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getWaypoints().isEmpty()).isTrue(); @@ -101,6 +103,8 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { final SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj; assertThat(new ArrayList<String>(search.getGeocodes())).isEqualTo(Collections.singletonList(geocode)); final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getWaypoints()).as("Number of imported waypoints").hasSize(4); @@ -128,6 +132,8 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { final SearchResult search = (SearchResult) importStepHandler.messages.get(4).obj; assertThat(new ArrayList<String>(search.getGeocodes())).isEqualTo(Collections.singletonList("GC31J2H")); final Geocache cache = DataStore.loadCache("GC31J2H", LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getWaypoints()).hasSize(2); } @@ -141,15 +147,17 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertImportStepMessages(GPXImporter.IMPORT_STEP_START, GPXImporter.IMPORT_STEP_READ_FILE, GPXImporter.IMPORT_STEP_STORE_STATIC_MAPS, GPXImporter.IMPORT_STEP_FINISHED); final Geocache cache = DataStore.loadCache("AID1", LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getName()).isEqualTo("First Aid Station #1"); } - private void assertImportStepMessages(int... importSteps) { - assertThat(importStepHandler.messages).hasSize(importSteps.length); - for (int i = 0; i < importSteps.length; i++) { + private void assertImportStepMessages(final int... importSteps) { + for (int i = 0; i < Math.min(importSteps.length, importStepHandler.messages.size()); i++) { assertThat(importStepHandler.messages.get(i).what).isEqualTo(importSteps[i]); } + assertThat(importStepHandler.messages).hasSize(importSteps.length); } public void testImportLoc() throws IOException { @@ -205,6 +213,8 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { final SearchResult search = (SearchResult) importStepHandler.messages.get(3).obj; assertThat(new ArrayList<String>(search.getGeocodes())).isEqualTo(Collections.singletonList(geocode)); final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getWaypoints().isEmpty()).isTrue(); @@ -223,6 +233,8 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { final SearchResult search = (SearchResult) importStepHandler.messages.get(4).obj; assertThat(new ArrayList<String>(search.getGeocodes())).isEqualTo(Collections.singletonList(geocode)); final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getWaypoints()).hasSize(1); // this is the original pocket query result without test waypoint } @@ -249,6 +261,8 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { final SearchResult search = (SearchResult) importStepHandler.messages.get(4).obj; assertThat(new ArrayList<String>(search.getGeocodes())).isEqualTo(Collections.singletonList(geocode)); final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + assert cache != null; + assertThat(cache).isNotNull(); assertCacheProperties(cache); assertThat(cache.getWaypoints()).hasSize(1); // this is the original pocket query result without test waypoint } diff --git a/tests/src/cgeo/geocaching/files/GPXParserTest.java b/tests/src/cgeo/geocaching/files/GPXParserTest.java index 6171bab..7c40b2a 100644 --- a/tests/src/cgeo/geocaching/files/GPXParserTest.java +++ b/tests/src/cgeo/geocaching/files/GPXParserTest.java @@ -6,14 +6,17 @@ import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; import cgeo.geocaching.Waypoint; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; import cgeo.geocaching.enumerations.WaypointType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; +import cgeo.geocaching.utils.CalendarUtils; import cgeo.geocaching.utils.SynchronizedDateFormat; import java.io.IOException; @@ -104,26 +107,25 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { assertGc31j2hWaypoints(cache); } + private static void checkWaypointType(final Collection<Geocache> caches, final String geocode, final int wpIndex, final WaypointType waypointType) { + for (final Geocache cache : caches) { + if (cache.getGeocode().equals(geocode)) { + final List<Waypoint> waypoints = cache.getWaypoints(); + assertThat(waypoints).isNotEmpty(); + final Waypoint waypoint = waypoints.get(wpIndex); + assertThat(waypoint).isNotNull(); + assertThat(waypoint.getWaypointType()).isEqualTo(waypointType); + return; + } + } + fail("could not find cache with geocode " + geocode); + } + public void testRenamedWaypointTypes() throws IOException, ParserException { - removeCacheCompletely("GC31J2H"); final List<Geocache> caches = readGPX10(R.raw.renamed_waypoints, R.raw.renamed_waypoints_wpts); assertThat(caches).hasSize(25); - // multi waypoint (now "physical stage") - Geocache cache = caches.get(12); - assertThat(cache.getGeocode()).isEqualTo("GC3NBDE"); - List<Waypoint> waypoints = cache.getWaypoints(); - assertThat(waypoints).isNotEmpty(); - Waypoint waypoint = waypoints.get(1); - assertThat(waypoint).isNotNull(); - assertThat(waypoint.getWaypointType()).isEqualTo(WaypointType.STAGE); - // mystery waypoint - now "virtual stage" - cache = caches.get(15); - assertThat(cache.getGeocode()).isEqualTo("GC16CBG"); - waypoints = cache.getWaypoints(); - assertThat(waypoints).isNotEmpty(); - waypoint = waypoints.get(1); - assertThat(waypoint).isNotNull(); - assertThat(waypoint.getWaypointType()).isEqualTo(WaypointType.PUZZLE); + checkWaypointType(caches, "GC3NBDE", 1, WaypointType.STAGE); // multi waypoint (now "physical stage") + checkWaypointType(caches, "GC16CBG", 1, WaypointType.PUZZLE); // mystery waypoint (now "virtual stage") } public void testGc31j2hWptsWithoutCache() throws IOException, ParserException { @@ -177,7 +179,7 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { assertThat(log.log).isEqualTo("Sehr schöne Runde und wir haben wieder etwas Neues über Hockenheim gelernt. Super Tarnung.\nTFTC, Geoteufel"); assertThat(log.isOwn()).isFalse(); assertThat(log.getDisplayText()).isEqualTo(log.log); - assertThat(log.daysSinceLog() > 700).isTrue(); + assertThat(CalendarUtils.daysSince(log.date) > 700).isTrue(); // following info is not contained in pocket query gpx file assertThat(cache.getAttributes()).isEmpty(); @@ -186,7 +188,7 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { private static long parseTime(final String time) { try { return LOG_DATE_FORMAT.parse(time).getTime(); - } catch (ParseException e) { + } catch (final ParseException e) { return 0; } } @@ -215,24 +217,24 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { assertEquals(8.545100, wp.getCoords().getLongitude(), 0.000001); } - private List<Geocache> readGPX10(int... resourceIds) throws IOException, ParserException { + private List<Geocache> readGPX10(final int... resourceIds) throws IOException, ParserException { final GPX10Parser parser = new GPX10Parser(getTemporaryListId()); return readVersionedGPX(parser, resourceIds); } - private List<Geocache> readGPX11(int... resourceIds) throws IOException, ParserException { + private List<Geocache> readGPX11(final int... resourceIds) throws IOException, ParserException { final GPX11Parser parser = new GPX11Parser(getTemporaryListId()); return readVersionedGPX(parser, resourceIds); } - private List<Geocache> readVersionedGPX(final GPXParser parser, int... resourceIds) throws IOException, ParserException { + private List<Geocache> readVersionedGPX(final GPXParser parser, final int... resourceIds) throws IOException, ParserException { final Set<String> result = new HashSet<String>(); - for (int resourceId : resourceIds) { + for (final int resourceId : resourceIds) { final InputStream instream = getResourceStream(resourceId); try { - Collection<Geocache> caches = parser.parse(instream, null); + final Collection<Geocache> caches = parser.parse(instream, null); assertThat(caches).isNotNull(); - for (Geocache cache : caches) { + for (final Geocache cache : caches) { result.add(cache.getGeocode()); } } finally { @@ -270,7 +272,7 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { final List<Geocache> caches = readGPX10(R.raw.geotoad); assertThat(caches).hasSize(2); final List<String> codes = new ArrayList<String>(); - for (Geocache cache : caches) { + for (final Geocache cache : caches) { codes.add(cache.getGeocode()); } assertThat(codes.contains("GC2KN6K")).isTrue(); @@ -286,6 +288,8 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { DataStore.removeAllFromCache(); // load only the minimum cache, it has several members missing final Geocache minimalCache = DataStore.loadCache(geocode, EnumSet.of(LoadFlag.DB_MINIMAL)); + assert minimalCache != null; + assertThat(minimalCache).isNotNull(); // now check that we load lazy members on demand assertThat(minimalCache.getAttributes()).isNotEmpty(); @@ -350,12 +354,11 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { assertThat(cache.getHint()).isEqualTo("Wasserleitung"); } - private Geocache getFirstCache(int gpxResourceId) throws IOException, ParserException { + private Geocache getFirstCache(final int gpxResourceId) throws IOException, ParserException { final List<Geocache> caches = readGPX10(gpxResourceId); assertThat(caches).isNotNull(); assertThat(caches).hasSize(1); - final Geocache cache = caches.get(0); - return cache; + return caches.get(0); } public void testGsakFavPoints() throws IOException, ParserException { @@ -375,14 +378,44 @@ public class GPXParserTest extends AbstractResourceInstrumentationTestCase { public void testGPXMysteryType() throws IOException, ParserException { final List<Geocache> caches = readGPX10(R.raw.tc2012); - Geocache mystery = null; - for (Geocache geocache : caches) { - if (geocache.getName().equals("U017")) { - mystery = geocache; - } - } + final Geocache mystery = getCache(caches, "U017"); assertThat(mystery).isNotNull(); - assert (mystery != null); + assert mystery != null; assertThat(mystery.getType()).isEqualTo(CacheType.MYSTERY); } + + private static Geocache getCache(final List<Geocache> caches, final String geocode) { + for (final Geocache geocache : caches) { + if (geocache.getName().equals(geocode)) { + return geocache; + } + } + return null; + } + + public void testLabCaches() throws IOException, ParserException { + final List<Geocache> caches = readGPX10(R.raw.giga_lab_caches); + assertThat(caches).hasSize(10); + final Geocache lab = getCache(caches, "01_Munich Olympic Walk Of Stars_Updated-Project MUNICH2014 - Mia san Giga! Olympiapark"); + assertThat(lab).isNotNull(); + + // parse labs as virtual for the time being + assertThat(lab.getType()).isEqualTo(CacheType.VIRTUAL); + + // no difficulty and terrain rating + assertThat(lab.getTerrain()).isEqualTo(0); + assertThat(lab.getDifficulty()).isEqualTo(0); + + // geocodes are just big hashes + assertThat(lab.getGeocode()).isEqualTo("01_Munich Olympic Walk Of Stars_Updated-Project MUNICH2014 - Mia san Giga! Olympiapark".toUpperCase(Locale.US)); + + // other normal cache properties + assertThat(lab.getName()).isEqualTo("01_Munich Olympic Walk Of Stars_Updated-Project MUNICH2014 - Mia san Giga! Olympiapark"); + assertThat(lab.getShortDescription()).isEqualTo("01_Munich Olympic Walk Of Stars_Updated (Giga! Olympia Park)-Project MUNICH2014 - Mia san Giga! Olympiapark"); + assertThat(lab.getDescription()).startsWith("DEU:"); + + final IConnector unknownConnector = ConnectorFactory.getConnector("ABC123"); + assertThat(ConnectorFactory.getConnector(lab)).isSameAs(unknownConnector); + } + } diff --git a/tests/src/cgeo/geocaching/files/LocParserTest.java b/tests/src/cgeo/geocaching/files/LocParserTest.java index d87b593..7d5ccee 100644 --- a/tests/src/cgeo/geocaching/files/LocParserTest.java +++ b/tests/src/cgeo/geocaching/files/LocParserTest.java @@ -5,7 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; diff --git a/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java b/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java deleted file mode 100644 index d8d099d..0000000 --- a/tests/src/cgeo/geocaching/files/SimpleDirChooserUITest.java +++ /dev/null @@ -1,94 +0,0 @@ -package cgeo.geocaching.files; - -import static org.assertj.core.api.Assertions.assertThat; - -import cgeo.geocaching.Intents; - -import com.robotium.solo.Solo; - -import android.annotation.TargetApi; -import android.content.Intent; -import android.os.Build; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.Suppress; -import android.widget.CheckBox; - -import java.util.ArrayList; - -@TargetApi(Build.VERSION_CODES.FROYO) -@Suppress -public class SimpleDirChooserUITest extends ActivityInstrumentationTestCase2<SimpleDirChooser> { - - private Solo solo; - - public SimpleDirChooserUITest() { - super(SimpleDirChooser.class); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - setActivityIntent(new Intent().putExtra(Intents.EXTRA_START_DIR, "").putExtra(SimpleDirChooser.EXTRA_CHOOSE_FOR_WRITING, false)); - solo = new Solo(getInstrumentation(), getActivity()); - } - - public ArrayList<CheckBox> getCurrentCheckBoxes() { - return solo.getCurrentViews(CheckBox.class); - } - - public void testSingleSelection() throws InterruptedException { - // normally our activity should be ready, but we already had Jenkins report no checkboxes right here at the beginning - solo.waitForActivity(solo.getCurrentActivity().getClass().getSimpleName(), 2000); - - assertChecked("Newly opened activity", 0); - solo.scrollToBottom(); - pause(); - // according to the documentation, automatic pauses only happen in the clickXYZ() methods. - // Therefore lets introduce a manual pause after the scrolling methods. - - final int lastIndex = getCurrentCheckBoxes().size() - 1; - - solo.clickOnCheckBox(lastIndex); - assertThat(solo.isCheckBoxChecked(lastIndex)).isTrue(); - assertThat(solo.isCheckBoxChecked(0)).isFalse(); - assertChecked("Clicked last checkbox", 1); - - solo.scrollUp(); - pause(); - solo.scrollToBottom(); - pause(); - assertChecked("Refreshing last checkbox", 1); - - solo.scrollToTop(); - pause(); - solo.clickOnCheckBox(0); - assertChecked("Clicked first checkbox", 1); - assertThat(solo.isCheckBoxChecked(0)).isTrue(); - solo.clickOnCheckBox(1); - assertChecked("Clicked second checkbox", 1); - assertThat(solo.isCheckBoxChecked(1)).isTrue(); - } - - private static void pause() throws InterruptedException { - Thread.sleep(100); - } - - private void assertChecked(String message, int expectedChecked) { - final ArrayList<CheckBox> boxes = getCurrentCheckBoxes(); - assertThat(boxes).as("Checkboxes").isNotNull(); - assertThat(boxes.size()).as("number of checkboxes").isGreaterThan(1); - int checked = 0; - for (int i = 0; i < boxes.size(); i++) { - if (solo.isCheckBoxChecked(i)) { - checked++; - } - } - assertEquals(message, expectedChecked, checked); - } - - @Override - public void tearDown() throws Exception { - solo.finishOpenedActivities(); - super.tearDown(); - } -} diff --git a/tests/src/cgeo/geocaching/filter/StateArchivedFilterTest.java b/tests/src/cgeo/geocaching/filter/StateArchivedFilterTest.java index d474857..3353fe9 100644 --- a/tests/src/cgeo/geocaching/filter/StateArchivedFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StateArchivedFilterTest.java @@ -4,11 +4,10 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StateArchivedFilter; public class StateArchivedFilterTest extends CGeoTestCase { - private StateFilter.StateArchivedFilter archivedFilter; + private StateFilterFactory.StateArchivedFilter archivedFilter; private Geocache archivedCache; @Override @@ -16,7 +15,7 @@ public class StateArchivedFilterTest extends CGeoTestCase { super.setUp(); // members can only be setup here, after application is initialized - archivedFilter = new StateArchivedFilter(); + archivedFilter = new StateFilterFactory.StateArchivedFilter(); archivedCache = new Geocache(); archivedCache.setArchived(true); } diff --git a/tests/src/cgeo/geocaching/filter/StateDisabledFilterTest.java b/tests/src/cgeo/geocaching/filter/StateDisabledFilterTest.java index 71a1134..eff3a67 100644 --- a/tests/src/cgeo/geocaching/filter/StateDisabledFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StateDisabledFilterTest.java @@ -4,18 +4,17 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StateDisabledFilter; public class StateDisabledFilterTest extends CGeoTestCase { - private StateFilter.StateDisabledFilter disabledFilter; + private StateFilterFactory.StateDisabledFilter disabledFilter; private Geocache disabledCache; @Override protected void setUp() throws Exception { super.setUp(); - disabledFilter = new StateDisabledFilter(); + disabledFilter = new StateFilterFactory.StateDisabledFilter(); disabledCache = new Geocache(); disabledCache.setDisabled(true); } diff --git a/tests/src/cgeo/geocaching/filter/StateFoundFilterTest.java b/tests/src/cgeo/geocaching/filter/StateFoundFilterTest.java index e763881..beedd51 100644 --- a/tests/src/cgeo/geocaching/filter/StateFoundFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StateFoundFilterTest.java @@ -4,18 +4,17 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StateFoundFilter; public class StateFoundFilterTest extends CGeoTestCase { - private StateFilter.StateFoundFilter foundFilter; + private StateFilterFactory.StateFoundFilter foundFilter; private Geocache foundCache; @Override protected void setUp() throws Exception { super.setUp(); - foundFilter = new StateFoundFilter(); + foundFilter = new StateFilterFactory.StateFoundFilter(); foundCache = new Geocache(); foundCache.setFound(true); } diff --git a/tests/src/cgeo/geocaching/filter/StateNonPremiumFilterTest.java b/tests/src/cgeo/geocaching/filter/StateNonPremiumFilterTest.java index c698e8b..87a8909 100644 --- a/tests/src/cgeo/geocaching/filter/StateNonPremiumFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StateNonPremiumFilterTest.java @@ -4,18 +4,17 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StateNonPremiumFilter; public class StateNonPremiumFilterTest extends CGeoTestCase { - private StateFilter.StateNonPremiumFilter nonPremiumFilter; + private StateFilterFactory.StateNonPremiumFilter nonPremiumFilter; private Geocache premiumCache; @Override protected void setUp() throws Exception { super.setUp(); - nonPremiumFilter = new StateNonPremiumFilter(); + nonPremiumFilter = new StateFilterFactory.StateNonPremiumFilter(); premiumCache = new Geocache(); premiumCache.setPremiumMembersOnly(true); } diff --git a/tests/src/cgeo/geocaching/filter/StateNotFoundFilterTest.java b/tests/src/cgeo/geocaching/filter/StateNotFoundFilterTest.java index 2bf9d94..bb5098c 100644 --- a/tests/src/cgeo/geocaching/filter/StateNotFoundFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StateNotFoundFilterTest.java @@ -4,18 +4,17 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StateNotFoundFilter; public class StateNotFoundFilterTest extends CGeoTestCase { - private StateFilter.StateNotFoundFilter notFoundFilter; + private StateFilterFactory.StateNotFoundFilter notFoundFilter; private Geocache foundCache; @Override protected void setUp() throws Exception { super.setUp(); - notFoundFilter = new StateNotFoundFilter(); + notFoundFilter = new StateFilterFactory.StateNotFoundFilter(); foundCache = new Geocache(); foundCache.setFound(true); } diff --git a/tests/src/cgeo/geocaching/filter/StatePremiumFilterTest.java b/tests/src/cgeo/geocaching/filter/StatePremiumFilterTest.java index ac8682b..c06a4fe 100644 --- a/tests/src/cgeo/geocaching/filter/StatePremiumFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StatePremiumFilterTest.java @@ -4,18 +4,17 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StatePremiumFilter; public class StatePremiumFilterTest extends CGeoTestCase { - private StateFilter.StatePremiumFilter premiumFilter; + private StateFilterFactory.StatePremiumFilter premiumFilter; private Geocache premiumCache; @Override protected void setUp() throws Exception { super.setUp(); - premiumFilter = new StatePremiumFilter(); + premiumFilter = new StateFilterFactory.StatePremiumFilter(); premiumCache = new Geocache(); premiumCache.setPremiumMembersOnly(true); } diff --git a/tests/src/cgeo/geocaching/filter/StateStoredFilterTest.java b/tests/src/cgeo/geocaching/filter/StateStoredFilterTest.java index d110921..5d1eecc 100644 --- a/tests/src/cgeo/geocaching/filter/StateStoredFilterTest.java +++ b/tests/src/cgeo/geocaching/filter/StateStoredFilterTest.java @@ -4,20 +4,18 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; import cgeo.geocaching.Geocache; -import cgeo.geocaching.filter.StateFilter.StateNotStoredFilter; -import cgeo.geocaching.filter.StateFilter.StateStoredFilter; public class StateStoredFilterTest extends CGeoTestCase { - private StateFilter.StateStoredFilter storedFilter; - private StateFilter.StateNotStoredFilter notStoredFilter; + private StateFilterFactory.StateStoredFilter storedFilter; + private StateFilterFactory.StateNotStoredFilter notStoredFilter; private Geocache cache; @Override protected void setUp() throws Exception { super.setUp(); - storedFilter = new StateStoredFilter(); - notStoredFilter = new StateNotStoredFilter(); + storedFilter = new StateFilterFactory.StateStoredFilter(); + notStoredFilter = new StateFilterFactory.StateNotStoredFilter(); cache = new Geocache(); } diff --git a/tests/src/cgeo/geocaching/gcvote/GCVoteTest.java b/tests/src/cgeo/geocaching/gcvote/GCVoteTest.java new file mode 100644 index 0000000..c1b5e75 --- /dev/null +++ b/tests/src/cgeo/geocaching/gcvote/GCVoteTest.java @@ -0,0 +1,47 @@ +package cgeo.geocaching.gcvote; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; +import cgeo.geocaching.test.R; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +public class GCVoteTest extends AbstractResourceInstrumentationTestCase { + + private InputStream responseStream; + + @Override + protected void setUp() throws Exception { + super.setUp(); + responseStream = new ByteArrayInputStream(getFileContent(R.raw.gcvote).getBytes()); + responseStream.mark(getFileContent(R.raw.gcvote).getBytes().length + 1); + } + + private InputStream responseStream() { + try { + responseStream.reset(); + } catch (final IOException ignored) { + // Cannot happen + } + return responseStream; + } + + public void testGetRatingsByGeocode() { + final Map<String, GCVoteRating> ratings = GCVote.getRatingsFromXMLResponse(responseStream(), false); + assertThat(ratings).hasSize(10); + assertThat(ratings).containsKey("GCKF13"); + assertThat(ratings.get("GC1WEVZ")).isEqualToComparingFieldByField(new GCVoteRating(3.75f, 2, 0)); + } + + public void testGetRatingsByGuid() { + final Map<String, GCVoteRating> ratings = GCVote.getRatingsFromXMLResponse(responseStream(), true); + assertThat(ratings).hasSize(10); + assertThat(ratings).containsKey("a02894bb-4a08-4c09-a73c-25939894ba15"); + assertThat(ratings.get("5520c33b-3941-45ca-9056-ea655dbaadf7")).isEqualToComparingFieldByField(new GCVoteRating(3.75f, 2, 0)); + } + +} diff --git a/tests/src/cgeo/geocaching/geopoint/DistanceParserTest.java b/tests/src/cgeo/geocaching/location/DistanceParserTest.java index 621d268..3641f6f 100644 --- a/tests/src/cgeo/geocaching/geopoint/DistanceParserTest.java +++ b/tests/src/cgeo/geocaching/location/DistanceParserTest.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import android.test.AndroidTestCase; @@ -23,7 +23,7 @@ public class DistanceParserTest extends AndroidTestCase { assertEquals(1.2, DistanceParser.parseDistance("1,2km", true), MM); } - public static void testCase() { + public static void testFeet() { assertEquals(0.36576, DistanceParser.parseDistance("1200 FT", true), MM); } diff --git a/tests/src/cgeo/geocaching/geopoint/GeoPointFormatterTest.java b/tests/src/cgeo/geocaching/location/GeoPointFormatterTest.java index 2816664..9ae54fa 100644 --- a/tests/src/cgeo/geocaching/geopoint/GeoPointFormatterTest.java +++ b/tests/src/cgeo/geocaching/location/GeoPointFormatterTest.java @@ -1,7 +1,9 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import static org.assertj.core.api.Assertions.assertThat; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.GeopointFormatter; import cgeo.geocaching.utils.Formatter; import android.test.AndroidTestCase; diff --git a/tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java b/tests/src/cgeo/geocaching/location/GeoPointParserTest.java index f8a3bb2..a2b916d 100644 --- a/tests/src/cgeo/geocaching/geopoint/GeoPointParserTest.java +++ b/tests/src/cgeo/geocaching/location/GeoPointParserTest.java @@ -1,4 +1,4 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import static org.assertj.core.api.Assertions.assertThat; @@ -41,6 +41,12 @@ public class GeoPointParserTest extends AndroidTestCase { assertThat(point).isNull(); } + public static void testCoordinateMissingDegree() { + // Some home coordinates on geocaching.com lack the degree part. + final Geopoint point = GeopointParser.parse("N 51° 23.123' W ° 17.123"); + assertThat(point).isEqualTo(new Geopoint("N", "51", "23", "123", "W", "0", "17", "123")); + } + public static void testSouth() { assertEquals(-refLatitude, GeopointParser.parseLatitude("S 49° 56.031"), 1e-8); } diff --git a/tests/src/cgeo/geocaching/location/GeocoderTest.java b/tests/src/cgeo/geocaching/location/GeocoderTest.java new file mode 100644 index 0000000..b7f10a3 --- /dev/null +++ b/tests/src/cgeo/geocaching/location/GeocoderTest.java @@ -0,0 +1,75 @@ +package cgeo.geocaching.location; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.CGeoTestCase; +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; +import org.assertj.core.data.Offset; + +import rx.Observable; + +import android.location.Address; +import android.location.Geocoder; + +import java.util.Locale; + +public class GeocoderTest extends CGeoTestCase { + + private static final String TEST_ADDRESS = "46 rue Barrault, Paris, France"; + private static final double TEST_LATITUDE = 48.82677; + private static final double TEST_LONGITUDE = 2.34644; + private static final Geopoint TEST_COORDS = new Geopoint(TEST_LATITUDE, TEST_LONGITUDE); + private static final Offset<Double> TEST_OFFSET = Offset.offset(0.00050); + + public static void testAndroidGeocoder() { + final Locale locale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + // Some emulators don't have access to Google Android geocoder + if (Geocoder.isPresent()) { + final AndroidGeocoder geocoder = new AndroidGeocoder(CgeoApplication.getInstance()); + testGeocoder(geocoder.getFromLocationName(TEST_ADDRESS), "Android", true); + testGeocoder(geocoder.getFromLocation(TEST_COORDS), "Android reverse", true); + } else { + Log.i("not testing absent Android geocoder"); + } + } finally { + Locale.setDefault(locale); + } + } + + public static void testGCGeocoder() { + testGeocoder(GCGeocoder.getFromLocationName(TEST_ADDRESS), "GC", false); + } + + public static void testMapQuestGeocoder() { + final Locale locale = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + testGeocoder(MapQuestGeocoder.getFromLocationName(TEST_ADDRESS), "MapQuest", true); + testGeocoder(MapQuestGeocoder.getFromLocation(TEST_COORDS), "MapQuest reverse", true); + } finally { + Locale.setDefault(locale); + } + } + + public static void testGeocoder(final Observable<Address> addressObservable, final String geocoder, final boolean withAddress) { + final Address address = addressObservable.toBlocking().first(); + assertThat(address.getLatitude()).as(describe("latitude", geocoder)).isCloseTo(TEST_LATITUDE, TEST_OFFSET); + assertThat(address.getLongitude()).as(describe("longitude", geocoder)).isCloseTo(TEST_LONGITUDE, TEST_OFFSET); + if (withAddress) { + assertThat(StringUtils.lowerCase(address.getAddressLine(0))).as(describe("street address", geocoder)).contains("barrault"); + assertThat(address.getLocality()).as(describe("locality", geocoder)).isEqualTo("Paris"); + assertThat(address.getCountryCode()).as(describe("country code", geocoder)).isEqualTo("FR"); + // don't assert on country name, as this can be localized, e.g. with the mapquest geocoder + } + } + + private static String describe(final String field, final String geocoder) { + return new StringBuilder(field).append(" for ").append(geocoder).append(" .geocoder").toString(); + } + +} diff --git a/tests/src/cgeo/geocaching/geopoint/GeopointTest.java b/tests/src/cgeo/geocaching/location/GeopointTest.java index 5db877a..6f5dd78 100644 --- a/tests/src/cgeo/geocaching/geopoint/GeopointTest.java +++ b/tests/src/cgeo/geocaching/location/GeopointTest.java @@ -1,8 +1,10 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.offset; +import cgeo.geocaching.location.Geopoint; + import android.os.Build; import android.os.Bundle; import android.test.AndroidTestCase; diff --git a/tests/src/cgeo/geocaching/geopoint/UnitsTest.java b/tests/src/cgeo/geocaching/location/UnitsTest.java index f208984..f03f6f0 100644 --- a/tests/src/cgeo/geocaching/geopoint/UnitsTest.java +++ b/tests/src/cgeo/geocaching/location/UnitsTest.java @@ -1,8 +1,9 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import static org.assertj.core.api.Assertions.assertThat; import cgeo.CGeoTestCase; +import cgeo.geocaching.location.Units; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.TestSettings; @@ -14,7 +15,7 @@ public class UnitsTest extends CGeoTestCase { final String actual = Units.getDistanceFromKilometers(distance); if (!StringUtils.equals(expected, actual.replace(',', '.'))) { // make 1.2 the same as 1,2 fail("getHumanDistance(" + distance + - ") [metric: " + (!Settings.isUseImperialUnits() ? "yes" : "no") + + ") [metric: " + (!Settings.useImperialUnits() ? "yes" : "no") + "] fails to match " + expected + ": " + actual); } } @@ -23,7 +24,7 @@ public class UnitsTest extends CGeoTestCase { @SuppressWarnings("static-method") public void testDistance() { assertThat(Units.getDistanceFromKilometers(null)).isEqualTo("?"); - final boolean savedImperial = Settings.isUseImperialUnits(); + final boolean savedImperial = Settings.useImperialUnits(); try { TestSettings.setUseImperialUnits(false); assertDistance("123 km", 122.782f); @@ -46,7 +47,7 @@ public class UnitsTest extends CGeoTestCase { @SuppressWarnings("static-method") public void testSpeed() { assertThat(Units.getDistanceFromKilometers(null)).isEqualTo("?"); - final boolean savedImperial = Settings.isUseImperialUnits(); + final boolean savedImperial = Settings.useImperialUnits(); try { TestSettings.setUseImperialUnits(false); assertSpeed("123 km/h", 122.782f); diff --git a/tests/src/cgeo/geocaching/geopoint/ViewportTest.java b/tests/src/cgeo/geocaching/location/ViewportTest.java index ace0356..be15458 100644 --- a/tests/src/cgeo/geocaching/geopoint/ViewportTest.java +++ b/tests/src/cgeo/geocaching/location/ViewportTest.java @@ -1,8 +1,10 @@ -package cgeo.geocaching.geopoint; +package cgeo.geocaching.location; import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.ICoordinates; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.location.Viewport; import org.eclipse.jdt.annotation.NonNull; diff --git a/tests/src/cgeo/geocaching/sensors/SensorsTest.java b/tests/src/cgeo/geocaching/sensors/SensorsTest.java index c4f70aa..6cedf50 100644 --- a/tests/src/cgeo/geocaching/sensors/SensorsTest.java +++ b/tests/src/cgeo/geocaching/sensors/SensorsTest.java @@ -3,11 +3,18 @@ package cgeo.geocaching.sensors; import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.MainActivity; +import cgeo.geocaching.utils.AngleUtils; + +import rx.Observable; import android.test.ActivityInstrumentationTestCase2; +import java.util.concurrent.TimeUnit; + public class SensorsTest extends ActivityInstrumentationTestCase2<MainActivity> { + private Sensors sensors; + public SensorsTest() { super(MainActivity.class); } @@ -15,11 +22,29 @@ public class SensorsTest extends ActivityInstrumentationTestCase2<MainActivity> @Override protected void setUp() throws Exception { super.setUp(); + sensors = Sensors.getInstance(); } public static void testGetDirectionNow() { - final float angle = DirectionProvider.getDirectionNow(1.0f); + final float angle = AngleUtils.getDirectionNow(1.0f); assertThat(angle == 1.0f || angle == 91.0f || angle == 181.0f || angle == 271.0f).isTrue(); } + private static <T> void testDataAvailability(final Observable<T> observable) { + try { + observable.timeout(200, TimeUnit.MILLISECONDS).first().toBlocking().single(); + } catch (final Exception ignored) { + fail("timeout while waiting for sensor data"); + } + } + + public void testDirectionObservable() { + testDataAvailability(sensors.directionObservable()); + } + + public void testGeodataObservable() { + testDataAvailability(sensors.geoDataObservable(false)); + testDataAvailability(sensors.geoDataObservable(true)); + } + } diff --git a/tests/src/cgeo/geocaching/settings/TestSettings.java b/tests/src/cgeo/geocaching/settings/TestSettings.java index 279f658..b82c120 100644 --- a/tests/src/cgeo/geocaching/settings/TestSettings.java +++ b/tests/src/cgeo/geocaching/settings/TestSettings.java @@ -37,7 +37,7 @@ public final class TestSettings extends Settings { } public static void setUseImperialUnits(final boolean imperial) { - putBoolean(R.string.pref_units, imperial); + putBoolean(R.string.pref_units_imperial, imperial); } public static void setCacheTwitterMessage(final String template) { diff --git a/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java b/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java index 0cfee49..51e7dae 100644 --- a/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java +++ b/tests/src/cgeo/geocaching/sorting/DistanceComparatorTest.java @@ -1,7 +1,7 @@ package cgeo.geocaching.sorting; import cgeo.geocaching.Geocache; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import android.test.AndroidTestCase; diff --git a/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java b/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java index 533135d..6d4fa46 100644 --- a/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java +++ b/tests/src/cgeo/geocaching/sorting/NameComparatorTest.java @@ -18,7 +18,7 @@ public class NameComparatorTest extends AndroidTestCase { } } - private NameComparator comp = new NameComparator(); + private final NameComparator comp = new NameComparator(); public void testLexical() { assertSorted(new NamedCache("A"), new NamedCache("Z")); @@ -38,11 +38,10 @@ public class NameComparatorTest extends AndroidTestCase { /** * Assert that a given collection of names is already sorted correctly. * - * @param names */ - private void assertSortedNames(String... names) { - ArrayList<Geocache> caches = new ArrayList<Geocache>(names.length); - for (String name : names) { + private void assertSortedNames(final String... names) { + final ArrayList<Geocache> caches = new ArrayList<Geocache>(names.length); + for (final String name : names) { caches.add(new NamedCache(name)); } Collections.sort(caches, comp); diff --git a/tests/src/cgeo/geocaching/speech/TextFactoryTest.java b/tests/src/cgeo/geocaching/speech/TextFactoryTest.java index c53aec9..c01fbd0 100644 --- a/tests/src/cgeo/geocaching/speech/TextFactoryTest.java +++ b/tests/src/cgeo/geocaching/speech/TextFactoryTest.java @@ -3,7 +3,7 @@ package cgeo.geocaching.speech; import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.CgeoApplication; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.settings.TestSettings; @@ -35,7 +35,7 @@ public class TextFactoryTest extends AndroidTestCase { final Configuration config = resources.getConfiguration(); defaultLocale1 = config.locale; defaultLocale2 = Locale.getDefault(); - defaultMetric = !Settings.isUseImperialUnits(); + defaultMetric = !Settings.useImperialUnits(); } @Override diff --git a/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java b/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java index eaac181..2a22895 100644 --- a/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java +++ b/tests/src/cgeo/geocaching/test/AbstractResourceInstrumentationTestCase.java @@ -75,7 +75,7 @@ public abstract class AbstractResourceInstrumentationTestCase extends Instrument protected void setUp() throws Exception { super.setUp(); temporaryListId = DataStore.createList("Temporary unit testing"); - assertThat(temporaryListId != StoredList.TEMPORARY_LIST_ID).isTrue(); + assertThat(temporaryListId != StoredList.TEMPORARY_LIST.id).isTrue(); assertThat(temporaryListId != StoredList.STANDARD_LIST_ID).isTrue(); } @@ -95,7 +95,7 @@ public abstract class AbstractResourceInstrumentationTestCase extends Instrument final protected Geocache loadCacheFromResource(int resourceId) throws IOException, ParserException { final InputStream instream = getResourceStream(resourceId); try { - GPX10Parser parser = new GPX10Parser(StoredList.TEMPORARY_LIST_ID); + GPX10Parser parser = new GPX10Parser(StoredList.TEMPORARY_LIST.id); Collection<Geocache> caches = parser.parse(instream, null); assertThat(caches).isNotNull(); assertThat(caches.isEmpty()).isFalse(); diff --git a/tests/src/cgeo/geocaching/test/CgeoTestsActivity.java b/tests/src/cgeo/geocaching/test/CgeoTestsActivity.java index c1f6fdd..8959ede 100644 --- a/tests/src/cgeo/geocaching/test/CgeoTestsActivity.java +++ b/tests/src/cgeo/geocaching/test/CgeoTestsActivity.java @@ -79,9 +79,7 @@ public class CgeoTestsActivity extends Activity { Thread.sleep(50); publishProgress(mReader.readLine()); } while (System.currentTimeMillis() < timeout); - } catch (InterruptedException e) { - publishProgress("ERROR: " + e); - } catch (IOException e) { + } catch (InterruptedException | IOException e) { publishProgress("ERROR: " + e); } finally { publishProgress("END"); diff --git a/tests/src/cgeo/geocaching/test/WhitespaceTest.java b/tests/src/cgeo/geocaching/test/WhitespaceTest.java index 1ce7cc8..110cdbc 100644 --- a/tests/src/cgeo/geocaching/test/WhitespaceTest.java +++ b/tests/src/cgeo/geocaching/test/WhitespaceTest.java @@ -30,8 +30,6 @@ public class WhitespaceTest extends AbstractResourceInstrumentationTestCase { * The place for the implementation to prove that the new version of replaceWhitespace is faster than * BaseUtils.replaceWhitespace() * - * @param data - * @return */ public static String replaceWhitespaceManually(final String data) { final int length = data.length(); @@ -39,7 +37,7 @@ public class WhitespaceTest extends AbstractResourceInstrumentationTestCase { data.getChars(0, length, chars, 0); int resultSize = 0; boolean lastWasWhitespace = true; - for (char c : chars) { + for (final char c : chars) { if (c == ' ' || c == '\n' || c == '\r' || c == '\t') { if (!lastWasWhitespace) { chars[resultSize++] = ' '; diff --git a/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.html b/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.html index 902fe7e..b50929b 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.html +++ b/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.html @@ -4,23 +4,19 @@ <html lang="en" class="no-js">
<head id="ctl00_Head1"><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><title>
GC1ZXX2 Hannopoly: Eislisenstrasse (Traditional Cache) in Niedersachsen, Germany created by Rich Uncle Pennybags
-</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" />
- <!--[if lt IE 8]>
- <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" />
- <![endif]-->
- <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" />
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta id="ctl00_ogUrl" property="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC1ZXX2&title=hannopoly-eislisenstrasse" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="Geocaching: the anytime, anywhere outdoor adventure game." /><meta name="twitter:description" content="There are millions of geocaches worldwide and probably even some near you right now. Visit Geocaching.com to see just how many geocaches are nearby and to get the free Official Geocaching app." /><meta name="twitter:image:src" content="https://www.geocaching.com/play/Content/images/preview-lg.jpg" /><meta name="author" content="Geocaching" /><meta name="DC.creator" content="Geocaching" /><meta name="Copyright" content="Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta name="p:domain_verify" content="107f8f596a30ff1ea307df82db696a5e" /><link href="//fonts.googleapis.com/css?family=Noto+Sans:400,700&subset=latin,latin-ext" rel="stylesheet" type="text/css" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link href="/content/coreCSS?v=LW0HKwsIsnIiQyE_ovDSvnj5M2xR0XjkVV3GaTHUlRI1" rel="stylesheet"/>
+<link href="/css/jqueryui1104/jqUI?v=G2XN-0HsvYJqSZehzmbzhJiIBnEZ9PaVHVjIweqiSx41" rel="stylesheet"/>
+<link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" /><script src="/bundle/modernizer?v=q--nrqGQx_uxNYSvw1AFPQRWLPih7RGk2o0lu9veYaY1"></script>
+<script src="/bundle/coreJS?v=uKjd3XRiFC1C29gkUc0JuDRCF6PuUu7R8PpzGjgXDEc1"></script>
+
+
<script type="text/javascript">
- var _gaq = _gaq || [];
- </script>
- <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script>
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
-
- <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js" type="text/javascript"></script>
- <script type="text/javascript" src="/js/jquery.truncate.min.js"></script>
-
- <script type='text/javascript'>
+
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
+
+ var _gaq = _gaq || [];
+
(function () {
var gads = document.createElement('script');
gads.async = true;
@@ -30,49 +26,67 @@ var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
- </script>
-
-
-
- <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" />
- <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" />
- <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" />
- <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.css" />
- <!--[if IE]>
- <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.ie.css" />
- <![endif]-->
- <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" />
- <script type="text/javascript" src="/js/leaflet/0.5.1/leaflet.js"></script>
- <script type="text/javascript" src="/js/geometa.js"></script>
- <script type="text/javascript">
- var userToken = null,
- urlParams = {},
- mapLatLng = null,
- cmapAdditionalWaypoints = [],
- initalLogs = null, totalLogs = 0, includeAvatars = false;
+ (function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments);
+ }, i[r].l = 1 * new Date();
+ a = s.createElement(o),
+ m = s.getElementsByTagName(o)[0];
+ a.async = 1; a.src = g;
+ m.parentNode.insertBefore(a, m);
+ })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
(function () {
- var e,
- d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); },
- q = window.location.search.substring(1),
- r = /([^&=]+)=?([^&]*)/g;
- while (e = r.exec(q)) {
- urlParams[d(e[1])] = d(e[2]);
- }
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+
})();
+
</script>
-<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC1ZXX2&title=hannopoly-eislisenstrasse&Submit6=Go" property="og:url" /><meta name="og:description" content="Use a smartphone or GPS device to navigate to the provided coordinates. Look for a other hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 1.5 and difficulty is 3 (out of 5)." property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/2.png" property="og:image" /><meta name="og:title" content="Hannopoly: Eislisenstrasse " property="og:title" /><script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="description" content="Hannopoly: Eislisenstrasse (GC1ZXX2) was created by Rich Uncle Pennybags on 10/16/2009. It's a Other size geocache, with difficulty of 3, terrain of 1.5. It's located in Niedersachsen, Germany. &nbsp; 1.Finde die Besitzrechtkarte im Cache&nbsp; 2. Notiere Dir die drei Grundstückspreise&nbsp; 3. Beachte die Informationen vor Ort&nbsp; 4. Finde die Bonus-Caches&nbsp; 5." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
+ + + + <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" /> + <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" /> + <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" /> + <link rel="stylesheet" type="text/css" media="all" href="/static/js/leaflet/0.7.2/leaflet.css" /> + <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" /> + <script type="text/javascript" src="/static/js/leaflet/0.7.2/leaflet.js"></script> + <script type="text/javascript"> + var userToken = null, + urlParams = {}, + mapLatLng = null, + cmapAdditionalWaypoints = [], + initalLogs = null, totalLogs = 0, includeAvatars = false; + + (function () { + var e, + d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); }, + q = window.location.search.substring(1), + r = /([^&=]+)=?([^&]*)/g; + + while (e = r.exec(q)) { + urlParams[d(e[1])] = d(e[2]); + } + })(); + </script> +<script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:description" content="Use a smartphone or GPS device to navigate to the provided coordinates. Look for a other hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 1.5 and difficulty is 3 (out of 5)." property="og:description" /><meta name="og:title" content="Hannopoly: Eislisenstrasse " property="og:title" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/2.png" property="og:image" /><meta name="description" content="Hannopoly: Eislisenstrasse (GC1ZXX2) was created by Rich Uncle Pennybags on 10/16/2009. It's a Other size geocache, with difficulty of 3, terrain of 1.5. It's located in Niedersachsen, Germany. &nbsp; 1.Finde die Besitzrechtkarte im Cache&nbsp; 2. Notiere Dir die drei Grundstückspreise&nbsp; 3. Beachte die Informationen vor Ort&nbsp; 4. Finde die Bonus-Caches&nbsp; 5." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
<body >
- <form name="aspnetForm" method="post" action="/geocache/GC1ZXX2_hannopoly-eislisenstrasse?Submit6=Go" id="aspnetForm">
+ <form name="aspnetForm" method="post" action="/geocache/GC1ZXX2_hannopoly-eislisenstrasse" id="aspnetForm">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
-<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="3" />
-<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE1Mzk0NTE5MTEPFgIeBEMuSUQoKVlTeXN0ZW0uSW50NjQsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQcxNDMzOTA5FgJmD2QWBmYPZBYKAgYPFgIeBFRleHQFYjxtZXRhIG5hbWU9IkNvcHlyaWdodCIgY29udGVudD0iQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4iIC8+ZAIHDxYCHwEFRzwhLS0gQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4gLS0+ZAIZDxYCHgRocmVmBR1+L2Nzcy90bG5NYXN0ZXJTY3JlZW4uY3NzP3I9MWQCGg8WAh8CBRV+L2Nzcy90bG5NYWluLmNzcz9yPTFkAh8PFgIeB1Zpc2libGVoZAIBDxYCHgZhY3Rpb24FNi9nZW9jYWNoZS9HQzFaWFgyX2hhbm5vcG9seS1laXNsaXNlbnN0cmFzc2U/U3VibWl0Nj1HbxYWAgsPFgIfAWRkAg0PZBYCAgUPFgIfA2cWCAIBDw8WAh4ISW1hZ2VVcmwFTmh0dHA6Ly9pbWcuZ2VvY2FjaGluZy5jb20vdXNlci9hdmF0YXIvZThhOTdhMDUtYTA1MS00ZGE5LWJjOTMtNmE4MzBiODY2YWZmLmpwZ2RkAgMPFgIfAQVsSGVsbG8sIDxhIGhyZWY9Ii9teS9kZWZhdWx0LmFzcHgiIHRpdGxlPSJWaWV3IFByb2ZpbGUgZm9yIEpvU2FNYUphIiBjbGFzcz0iU2lnbmVkSW5Qcm9maWxlTGluayI+Sm9TYU1hSmE8L2E+ZAIFDw8WAh4LTmF2aWdhdGVVcmwFuQFodHRwczovL3d3dy5nZW9jYWNoaW5nLmNvbS9sb2dpbi9kZWZhdWx0LmFzcHg/UkVTRVQ9WSZyZWRpcj1odHRwJTNhJTJmJTJmd3d3Lmdlb2NhY2hpbmcuY29tJTJmc2VlayUyZmNhY2hlX2RldGFpbHMuYXNweCUzZndwJTNkR0MxWlhYMiUyNnRpdGxlJTNkaGFubm9wb2x5LWVpc2xpc2Vuc3RyYXNzZSUyNlN1Ym1pdDYlM2RHb2RkAgsPFgIfAQUQNDg0IENhY2hlcyBGb3VuZGQCFw8WAh8DZxYCAg0PDxYCHwYFQH4vdHJhY2svc2VhcmNoLmFzcHg/bz0xJnVpZD00ZDQxNjQ2MS1kMWE3LTRjYzUtOGVlNy0zMzZiYjkxMGZlYjhkZAIdDw8WAh8DZ2RkAikPFgIfA2dkAlcPZBYEAgMPFgIfAQUHRW5nbGlzaGQCBQ8WAh4LXyFJdGVtQ291bnQCFBYoZg9kFgICAQ8PFggeD0NvbW1hbmRBcmd1bWVudAUFZW4tVVMeC0NvbW1hbmROYW1lBQ1TZXRUZW1wTG9jYWxlHwEFB0VuZ2xpc2geEENhdXNlc1ZhbGlkYXRpb25oZGQCAQ9kFgICAQ8PFggfCAUFZGUtREUfCQUNU2V0VGVtcExvY2FsZR8BBQdEZXV0c2NoHwpoZGQCAg9kFgICAQ8PFggfCAUFZnItRlIfCQUNU2V0VGVtcExvY2FsZR8BBQlGcmFuw6dhaXMfCmhkZAIDD2QWAgIBDw8WCB8IBQVwdC1QVB8JBQ1TZXRUZW1wTG9jYWxlHwEFClBvcnR1Z3XDqnMfCmhkZAIED2QWAgIBDw8WCB8IBQVjcy1DWh8JBQ1TZXRUZW1wTG9jYWxlHwEFCcSMZcWhdGluYR8KaGRkAgUPZBYCAgEPDxYIHwgFBWRhLURLHwkFDVNldFRlbXBMb2NhbGUfAQUFRGFuc2sfCmhkZAIGD2QWAgIBDw8WCB8IBQVzdi1TRR8JBQ1TZXRUZW1wTG9jYWxlHwEFB1N2ZW5za2EfCmhkZAIHD2QWAgIBDw8WCB8IBQVlcy1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFCEVzcGHDsW9sHwpoZGQCCA9kFgICAQ8PFggfCAUFZXQtRUUfCQUNU2V0VGVtcExvY2FsZR8BBQVFZXN0aR8KaGRkAgkPZBYCAgEPDxYIHwgFBWl0LUlUHwkFDVNldFRlbXBMb2NhbGUfAQUISXRhbGlhbm8fCmhkZAIKD2QWAgIBDw8WCB8IBQVlbC1HUh8JBQ1TZXRUZW1wTG9jYWxlHwEFEM6VzrvOu863zr3Ouc66zqwfCmhkZAILD2QWAgIBDw8WCB8IBQVsdi1MVh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUxhdHZpZcWhdR8KaGRkAgwPZBYCAgEPDxYIHwgFBW5sLU5MHwkFDVNldFRlbXBMb2NhbGUfAQUKTmVkZXJsYW5kcx8KaGRkAg0PZBYCAgEPDxYIHwgFBWNhLUVTHwkFDVNldFRlbXBMb2NhbGUfAQUHQ2F0YWzDoB8KaGRkAg4PZBYCAgEPDxYIHwgFBXBsLVBMHwkFDVNldFRlbXBMb2NhbGUfAQUGUG9sc2tpHwpoZGQCDw9kFgICAQ8PFggfCAUFbmItTk8fCQUNU2V0VGVtcExvY2FsZR8BBQ5Ob3JzaywgQm9rbcOlbB8KaGRkAhAPZBYCAgEPDxYIHwgFBWtvLUtSHwkFDVNldFRlbXBMb2NhbGUfAQUJ7ZWc6rWt7Ja0HwpoZGQCEQ9kFgICAQ8PFggfCAUFaHUtSFUfCQUNU2V0VGVtcExvY2FsZR8BBQZNYWd5YXIfCmhkZAISD2QWAgIBDw8WCB8IBQVyby1STx8JBQ1TZXRUZW1wTG9jYWxlHwEFCFJvbcOibsSDHwpoZGQCEw9kFgICAQ8PFggfCAUFamEtSlAfCQUNU2V0VGVtcExvY2FsZR8BBQnml6XmnKzoqp4fCmhkZAJbD2QWAgIDDxYCHwNoZAJdDxYCHgVjbGFzcwUMc3Bhbi0yNCBsYXN0FgICAQ9kFioCAQ9kFgJmD2QWAgIBDw8WAh8BBQdHQzFaWFgyZGQCAg8WAh8BBaYBPGEgaHJlZj0iL2Fib3V0L2NhY2hlX3R5cGVzLmFzcHgiIHRhcmdldD0iX2JsYW5rIiB0aXRsZT0iQWJvdXQgQ2FjaGUgVHlwZXMiPjxpbWcgc3JjPSIvaW1hZ2VzL1dwdFR5cGVzLzIuZ2lmIiBhbHQ9IlRyYWRpdGlvbmFsIENhY2hlIiB0aXRsZT0iVHJhZGl0aW9uYWwgQ2FjaGUiIC8+PC9hPmQCBg9kFgQCAQ8WAh8DZ2QCBw8WAh8DaGQCCg9kFgYCAQ8WAh8BBQI0MmQCBQ8WAh8DaGQCBw8PFgIfBgVEL3NlZWsvY2FjaGVfZmF2b3JpdGVkLmFzcHg/Z3VpZD0zNmQ0NTg3MS1iOTlkLTQ2ZDYtOTVmYy1mZjg2YWI1NjRjOThkZAIMDw8WAh8DaGRkAg4PFgQfAQW+ATxwIGNsYXNzPSJPbGRXYXJuaW5nIE5vQm90dG9tU3BhY2luZyI+PHN0cm9uZz5DYWNoZSBJc3N1ZXM6PC9zdHJvbmc+PC9wPjx1bCBjbGFzcz0iT2xkV2FybmluZyI+PGxpPlRoaXMgY2FjaGUgaGFzIGJlZW4gYXJjaGl2ZWQsIGJ1dCBpcyBhdmFpbGFibGUgZm9yIHZpZXdpbmcgZm9yIGFyY2hpdmFsIHB1cnBvc2VzLjwvbGk+PC91bD4fA2dkAg8PFgIfA2hkAhAPFgIfA2hkAhEPZBYMAgMPZBYCAgEPFgIfAQUbVVRNOiAzMlUgRSA1NDgzODkgTiA1ODAyNzg3ZAINDw8WAh8GBTNjZHBmLmFzcHg/Z3VpZD0zNmQ0NTg3MS1iOTlkLTQ2ZDYtOTVmYy1mZjg2YWI1NjRjOThkZAIPDw8WAh8GBThjZHBmLmFzcHg/Z3VpZD0zNmQ0NTg3MS1iOTlkLTQ2ZDYtOTVmYy1mZjg2YWI1NjRjOTgmbGM9NWRkAhEPDxYCHwYFOWNkcGYuYXNweD9ndWlkPTM2ZDQ1ODcxLWI5OWQtNDZkNi05NWZjLWZmODZhYjU2NGM5OCZsYz0xMGRkAhMPDxYEHwYFgwFodHRwOi8vbWFwcy5nb29nbGUuY29tL21hcHM/Zj1kJmhsPWVuJnNhZGRyPTUyLjIxNjI1LDkuNzE0NDgzIChIb21lIExvY2F0aW9uKSZkYWRkcj01Mi4zNzMyMTcsOS43MTA4KEhhbm5vcG9seSUzYStFaXNsaXNlbnN0cmFzc2UrKR4GVGFyZ2V0BQZfYmxhbmtkZAIbD2QWCGYPDxYEHglGb3JlQ29sb3IMHgRfIVNCAgRkZAIBDw8WBB8NDB8OAgRkZAICDw8WAh8DZxYCHgdvbmNsaWNrBTtzMmdwcygnMzZkNDU4NzEtYjk5ZC00NmQ2LTk1ZmMtZmY4NmFiNTY0Yzk4Jyk7cmV0dXJuIGZhbHNlO2QCAw8PFgIfA2cWAh8PBSBzMnBob25lKCdHQzFaWFgyJyk7cmV0dXJuIGZhbHNlO2QCEw8WAh8DZ2QCFw9kFghmDxYCHwNoZAIBDw8WAh8DaGRkAgIPDxYCHwNoZGQCAw8WAh8DaGQCGA9kFgICAw8PFgIfAQUTTm8gaGludHMgYXZhaWxhYmxlLhYCHw8FDXJldHVybiBmYWxzZTtkAhkPFgIfA2hkAhsPZBYEAgEPFgQfAgUfL3NlZWsvbG9nLmFzcHg/SUQ9MTQzMzkwOSZsY249MR4JaW5uZXJodG1sBQ5Mb2cgeW91ciB2aXNpdGQCAg8WAh8DaGQCHA8WAh8DZ2QCHQ8WAh8DaGQCIA9kFgICAw8WAh8QBRNBZHZlcnRpc2luZyB3aXRoIFVzZAIkD2QWBAIFDw8WAh8DZ2RkAgkPDxYCHwYFPH4vdHJhY2svc2VhcmNoLmFzcHg/d2lkPTM2ZDQ1ODcxLWI5OWQtNDZkNi05NWZjLWZmODZhYjU2NGM5OGRkAiUPDxYCHwNnZBYCZg8WAh8HAgMW" />
-<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="BgIBD2QWAmYPFQIA6gE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD00MWNkNTZiNi0wMGYxLTQ3MDItYjg2Ni0xYTI2OGM2NDlkMTMiPkFsbGUgSGFubm9wb2x5IENhY2hlczwvYT48YnIgLz4gYnkgPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPWRmMjE4NGFiLWE5ZWEtNGQzMC05OGVkLWVjNGU4NTFjMzcwNiI+R3VtbWlzZWVsZTwvYT5kAgIPZBYCZg8VAg5BbHRlcm5hdGluZ1Jvd+EBPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9ib29rbWFya3Mvdmlldy5hc3B4P2d1aWQ9MGRjZjNmODYtOTM3Mi00OTljLThiNTctZWQ0MTliZDQ4ZTIxIj5NZWluZSBFbXBmZWhsdW5nPC9hPjxiciAvPiBieSA8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3Byb2ZpbGUvP2d1aWQ9YzQ2NTQxZmMtNmFlOS00NDUyLTg4MzMtNDcwZGRmYmU5Y2VlIj5za3JlbGw8L2E+ZAIDD2QWAmYPFQIA2wE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD05YTI0OGRiOS0zMDYzLTQ0NTctOTIwNS04NTFmYmUwNmEwM2UiPkhhbm5vcG9seTwvYT48YnIgLz4gYnkgPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPTVjNGIwOTE1LTVjZWMtNGZhMS04YWZkLTRiM2NhNjdlMDA0ZSI+a2FpMjcwNzwvYT5kAiYPDxYCHwNnZBYCZg8WAh8HAgEWAgIBD2QWAmYPFQIA3QE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD0xNDU1MTcwOC0wYzNjLTRmOTUtOTM0Mi0xYmIzMTE5ZTZlZmUiPmNnZW8gbW9ja3M8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD00ZDQxNjQ2MS1kMWE3LTRjYzUtOGVlNy0zMzZiYjkxMGZlYjgiPkpvU2FNYUphPC9hPmQCJw9kFhICAQ8PFgIfA2hkZAIDD2QWAgIBDw8WAh8GBUUvaGlkZS93cHRsaXN0LmFzcHg/UmVmV3B0SUQ9MzZkNDU4NzEtYjk5ZC00NmQ2LTk1ZmMtZmY4NmFiNTY0Yzk4JkRTPTFkZAIHDw8WBh4GUkRTLklECyl2R3JvdW5kc3BlYWsuV2ViLkdQWC5XcHREYXRhU291cmNlcywgVHVjc29uLkNvbW1vbi5MZWdhY3ksIFZlcnNpb249My4wLjQ5ODEuMTMyOTMsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAEeB1JXUFQuSUQoKwQHMTQzMzkwOR8DaGRkAgkPDxYCHwNnZBYCAgEPDxYEHwYFKi9tYXAvZGVmYXVsdC5hc3B4P2xhdD01Mi4zNzMyMTcmbG5nPTkuNzEwOB8DZ2RkAg8PFgIfAQWHAS4uLm90aGVyIGNhY2hlcyA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dT1kYW5pZWwzNTQiPmhpZGRlbjwvYT4gb3IgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P3VsPWRhbmllbDM1NCI+Zm91bmQ8L2E+IGJ5IHRoaXMgdXNlcmQCEQ9kFgYCAQ8WAh8BBf8BLi4ubmVhcmJ5IDxhIGhyZWY9Ii9zZWVrL25lYXJlc3QuYXNweD90eD0zMmJjOTMzMy01ZTUyLTQ5NTctYjBmNi01YTJjOGZjN2IyNTcmbGF0PTUyLjM3MzIxNyZsbmc9OS43MTA4MDAiPmNhY2hlcyBvZiB0aGlzIHR5cGU8L2E+LCA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dHg9MzJiYzkzMzMtNWU1Mi00OTU3LWIwZjYtNWEyYzhmYzdiMjU3JmxhdD01Mi4zNzMyMTcmbG5nPTkuNzEwODAwJmY9MSI+dGhhdCBJIGhhdmVuJ3QgZm91bmQ8L2E+ZAIDDxYCHwEFpgEuLi5hbGwgbmVhcmJ5IDxhIGhyZWY9Ii9zZWVrL25lYXJlc3QuYXNweD9sYXQ9NTIuMzczMjE3JmxuZz05LjcxMDgwMCI+Y2FjaGVzPC9hPiwgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P2xhdD01Mi4zNzMyMTcmbG5nPTkuNzEwODAwJmY9MSI+dGhhdCBJIGhhdmVuJ3QgZm91bmQ8L2E+ZAIFDxYCHwEFfi4uLmFsbCBuZWFyYnkgPGEgaHJlZj0iaHR0cDovL3d3dy53YXltYXJraW5nLmNvbS9kaXJlY3RvcnkuYXNweD9mPTEmbGF0PTUyLjM3MzIxNyZsb249OS43MTA4MDAiPndheW1hcmtzIG9uIFdheW1hcmtpbmcuY29tPC9hPmQCEw8WAh8DaGQCFw9kFgICAQ8PFgQfAQWuBzxsaT48YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL21hcC9kZWZhdWx0LmFzcHg/bGF0PTUyLjM3MzIyJmxuZz05LjcxMDgiIHRhcmdldD0iX2JsYW5rIj5HZW9jYWNoaW5nLmNvbSBNYXA8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL21hcHMuZ29vZ2xlLmNvbS9tYXBzP3E9Tis1MiVjMiViMCsyMi4zOTMrRSswMDklYzIlYjArNDIuNjQ4KyhHQzFaWFgyKSsiIHRhcmdldD0iX2JsYW5rIj5Hb29nbGUgTWFwczwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vd3d3Lm1hcHF1ZXN0LmNvbS9tYXBzL21hcC5hZHA/c2VhcmNodHlwZT1hZGRyZXNzJmZvcm10eXBlPWxhdGxvbmcmbGF0bG9uZ3R5cGU9ZGVjaW1hbCZsYXRpdHVkZT01Mi4zNzMyMiZsb25naXR1ZGU9OS43MTA4Jnpvb209MTAiIHRhcmdldD0iX2JsYW5rIj5NYXBRdWVzdDwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vbWFwcy55YWhvby5jb20vI2xhdD01Mi4zNzMyMiZsb249OS43MTA4Jnpvb209MTYmcT01Mi4zNzMyMiw5LjcxMDgmY29uZj0xJnN0YXJ0PTEmbXZ0PW0mdHJmPTAiIHRhcmdldD0iX2JsYW5rIj5ZYWhvbyBNYXBzPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly93d3cuYmluZy5jb20vbWFwcy9kZWZhdWx0LmFzcHg/dj0yJmx2bD0xNCZzcD1wb2ludC41Mi4zNzMyMl85LjcxMDhfR0MxWlhYMiIgdGFyZ2V0PSJfYmxhbmsiPkJpbmcgTWFwczwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vd3d3Lm9wZW5jeWNsZW1hcC5vcmcvP3pvb209MTImbGF0PTUyLjM3MzIyJmxvbj05LjcxMDgiIHRhcmdldD0iX2JsYW5rIj5PcGVuQ3ljbGVNYXA8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy8/bWxhdD01Mi4zNzMyMiZtbG9uPTkuNzEwOCZ6b29tPTEyIiB0YXJnZXQ9Il9ibGFuayI+T3BlblN0cmVldE1hcDwvYT48L2xpPh8DZ2RkAhsPZBYGAgEPFgIfAQURNDAwIExvZ2dlZCBWaXNpdHNkAgcPDxYCHwYFQ34vc2Vlay9jYWNoZV9sb2dib29rLmFzcHg/Z3VpZD0zNmQ0NTg3MS1iOTlkLTQ2ZDYtOTVmYy1mZjg2YWI1NjRjOThkZAIJDw8WBB8GBT1+L3NlZWsvZ2FsbGVyeS5hc3B4P2d1aWQ9MzZkNDU4NzEtYjk5ZC00NmQ2LTk1ZmMtZmY4NmFiNTY0Yzk4HwEFIlZpZXcgdGhlIEltYWdlIEdhbGxlcnkgb2YgMiBpbWFnZXNkZAJfDxYCHwNoFgICAQ8PZBYCHgVzdHlsZQUMd2lkdGg6MTIwcHg7ZAJhD2QWBAIDDxYCHwEFB0VuZ2xpc2hkAgUPFgIfBwIUFihmD2QWAgIBDw8WCB8IBQVlbi1VUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0VuZ2xpc2gfCmhkZAIBD2QWAgIBDw8WCB8IBQVkZS1ERR8JBQ1TZXRUZW1wTG9jYWxlHwEFB0RldXRzY2gfCmhkZAICD2QWAgIBDw8WCB8IBQVmci1GUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUZyYW7Dp2Fpcx8KaGRkAgMPZBYCAgEPDxYIHwgFBXB0LVBUHwkFDVNldFRlbXBMb2NhbGUfAQUKUG9ydHVndcOqcx8KaGRkAgQPZBYCAgEPDxYIHwgFBWNzLUNaHwkFDVNldFRlbXBMb2NhbGUfAQUJxIxlxaF0aW5hHwpoZGQCBQ9kFgICAQ8PFggfCAUFZGEtREsfCQUNU2V0VGVtcExvY2FsZR8BBQVEYW5zax8KaGRkAgYPZBYCAgEPDxYIHwgFBXN2LVNFHwkFDVNldFRlbXBMb2NhbGUfAQUHU3ZlbnNrYR8KaGRkAgcPZBYCAgEPDxYIHwgFBWVzLUVTHwkFDVNldFRlbXBMb2NhbGUfAQUIRXNwYcOxb2wfCmhkZAIID2QWAgIBDw8WCB8IBQVldC1FRR8JBQ1TZXRUZW1wTG9jYWxlHwEFBUVlc3RpHwpoZGQCCQ9kFgICAQ8PFggfCAUFaXQtSVQfCQUN" />
-<input type="hidden" name="__VIEWSTATE2" id="__VIEWSTATE2" value="U2V0VGVtcExvY2FsZR8BBQhJdGFsaWFubx8KaGRkAgoPZBYCAgEPDxYIHwgFBWVsLUdSHwkFDVNldFRlbXBMb2NhbGUfAQUQzpXOu867zrfOvc65zrrOrB8KaGRkAgsPZBYCAgEPDxYIHwgFBWx2LUxWHwkFDVNldFRlbXBMb2NhbGUfAQUJTGF0dmllxaF1HwpoZGQCDA9kFgICAQ8PFggfCAUFbmwtTkwfCQUNU2V0VGVtcExvY2FsZR8BBQpOZWRlcmxhbmRzHwpoZGQCDQ9kFgICAQ8PFggfCAUFY2EtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQdDYXRhbMOgHwpoZGQCDg9kFgICAQ8PFggfCAUFcGwtUEwfCQUNU2V0VGVtcExvY2FsZR8BBQZQb2xza2kfCmhkZAIPD2QWAgIBDw8WCB8IBQVuYi1OTx8JBQ1TZXRUZW1wTG9jYWxlHwEFDk5vcnNrLCBCb2ttw6VsHwpoZGQCEA9kFgICAQ8PFggfCAUFa28tS1IfCQUNU2V0VGVtcExvY2FsZR8BBQntlZzqta3slrQfCmhkZAIRD2QWAgIBDw8WCB8IBQVodS1IVR8JBQ1TZXRUZW1wTG9jYWxlHwEFBk1hZ3lhch8KaGRkAhIPZBYCAgEPDxYIHwgFBXJvLVJPHwkFDVNldFRlbXBMb2NhbGUfAQUIUm9tw6JuxIMfCmhkZAITD2QWAgIBDw8WCB8IBQVqYS1KUB8JBQ1TZXRUZW1wTG9jYWxlHwEFCeaXpeacrOiqnh8KaGRkApUBDxYCHwEFECZjb3B5OyAyMDAwLTIwMTNkAgMPFgIfAQUrU2VydmVyOiBXRUIxNzsgQnVpbGQ6IFdlYi5Ib3RGaXhfMjAxMzA4MjEuMWRk8TRGBQCzenLjJWEEfUCp5MnIoFo=" />
+<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="RIvZ3+uYIV9tlk5fq4AEqnMOm9mWoL8BN8jmivfMOgNqShDrgfeHb4MUYqYOnXvkqAWspLPtX1Wca4ikRD4YRU84n30a3tf2CYYtSvx7GtdIjPEk9bPdPZW1hBNr5WWL+QAN0JURazNMYX15Yxil1C0iLXjKDQgCbJboMfdI8fxJF1/o/CSH+oSbQ48Ku6D4byfHIBJVXogyMmnpc+ycRc/paN0CC1IQF5BZ7dHBK/t3M+O944pYe7EXDG03AkiIZn6lMcU7dm5D62qp/GkgJ6YnH3nIevnx9wA1YuwuGor1J+pBQWUAVEiH3gVbf+oez/dHvMaMRSn66O+7tOfgwg5YOw4S2KB8rzh61Uj0m5WgBbhf7IbnIXcxWyyrSiwHZXad/eVE0vBt9TcKdsT+zFrQZQRUHSxISksWqv5nyUwadas8sdXxSy0IzQKRWa+DwQedx9Q3giPe9dy3b2yjl4JDlAisSA0LtFuFN6kKGqLXzxwd0zsXnkn3JsFiSOmBM7bwfbpO+NBumNpQ9F2h+Yj0Ucl/E/wYvLfB7g8n2XoeNtn3g6swvDITB6W/XCyOGGSiJ8NRVeXfJhuUV3sgW/rm/r8aXNHCSoeXtSYhMP1BGFDkkaoNQ4JOiLZhhS5GP3O4AZ0/mmc95c6wEC9NgWk96Y7aMDegT3RGEW7x8vXJofkQVn9UbieByRzP6J2H6uuBSQ97UaHER9i0c+xJgHn/vn8mjWHk+bSldJE893Np7qGOCWKFYrCiu7IXMZJBYIsY4tg68hADxzvD0q8KikJA1fWR4a+AUwa6qkHJ+QDL6rWE/pCGa18pEPI9eXq1xKqTHZNB98dYf8cbJaFpAgjcv1KdIFYggnktNojcjFU6ozqsaHm5zf0QL98SBE2faozoKz8YL1iVG6pVm6mqgC3wb+mKVtJluFnyL2GT5/OwcnP0w/4OlbTI94B0wII/2o5TL+EZBa7kthEVSQ0mg6P9VNnEDWnyMN9FXoM7Ake8k5OAaBosraKG3dywFlAJRJkqEL1wndpu/EEBZzrsvekTHssIUQs/kEj2o7LxqAhctJRO8HoyVSwDfdK0ACV9yJHqxdwpKKGfymPZFmkPII0t0pkgZQxhO81vMYg5uDOhV2IRTgFnCT4u1z6xAINmBF2yv4FjQ5M/CIJIZ/0BYFzrQ3Nbqc74dO7irHtaul70GTvBThQV9A6yzIDytwOOjQXMLeRGHlmd+TuDyPLbMI5xtoDbPP9pBPj/mVIIAgrkUFcKNOyZLrtGJTtRWb0xnwMFR36NFekKSDK+igGVGueFwBOtNqdHQ7SKc7JA5KojAmESWda3dzNzi7m5IQiAKg3zxKOm9naYcheq/0QcEQI1EpFvykejs25Xf0mk2sE7+wPekHZ9GHa311XXvUWeOIzeoUsKSJlKa0eSu5yUr05sRjzsE4QqnyyQuiOQojFzxuIvGHmB7MwNSWiiM9azjaDa7RixtgubBsxLAIS4sl/DzGrb0ahTShYnK8ruFKxlI0a97ayo9aHp+7SOoyf73WP2S4R6NEtnpl8rs4vkHBS1TEtfWGC49H9g0gx8YHFGDY/CG1/GUl4vgMkzMp9rxqCanWuWwuMwWUl1gxupXB4fnxGTE5YMemNmLugtqn+yHW0flXkWF933v1uG7ed9R+4Fvt+YxoYy4Ca+xY1AoPy6+NVFyZfKGEpxF8eDJKus0qwcQ0mWSkb9eE46prJrBHB8uxwm9XPqHLBarlPpF27FJAilG4XL2+S700UoBu0KghF+tfkD8QOUWW9XRSj0yiFVCTAUtTfR4+SlkF3rLaP5Qg9v4/r2+eYPcWZYTI+JpMJq2pciqxHCFE2v0iK0xs7twn9SkcIUlTXCbEaNhL7ndINU+ExDSAFhAUgqLiCp/NHl4D2W5WsdGbyfvnLiguE6Hu401aEYOiebQ/acyZ0Eq+3e+TbCVp9yekTzw8Toc7yBQYuZcBhvSEAT3wizQlKA8VMm5lcSGB+K53q4Hgc3klQYQCKJ7VjE6/6AM09047YZ34d95pNkBv44GwX0Exbg8hcB4OAYh0vDz7m7hq5kp7TLd57o0flhE0p++tOQPPz5s31RMiuvV53YGXhUAKpA8eug/rGryfakOrz4zrpG8BfYV9iwgW59svAL8aCowO9JK5fiFKnFL0S7Nw2rV8wsS1SsbzHyPn+FIOSXJmm8MhdQRM9GmJJ9e0lMTDc6JjV9lTXf8C9qaTRpfqBJltY+2o1BsWwvqz/NGLYUqMlInwyJY5dGUQBjT6fUA0dPNsyPmZbZbM/2x1ii5e1hop/mDbFuDHoSQHJ54holyMKJM9+aby5q+iWUvNv/yYGJxCShPEjXZmJFu9z214AaTmx6lyO95HqhnU9YSVL4NvqdMuXYaVNxvQTzsCv9M5dn3e/vbn8/f/hMrPWGJPicQe1dIuX35yeAh7Gq8iMgzRPmsbPMoyTSo/La2e2tVqfxrJeISBMr++Q7ZhP2iPtYKinOP6t5w/QTFBuW3JR0SHvf+WLXlO6WrFd1S5c6poOKHORb+v3DW5scUpBPpOlYeZBKXPp5iXYSVTKK6jnx+ixeSh79Cha9mLbze1bfKNHgd7AvcEOeJYuPcwfSi+eWOVVjxs+y5rcCbYkTpLBQbFfY0obEyckV1CMxc6NmlbpHJ+HADQYnE0FfCSp0Zpx2ysuzCJ0tk45R0o6NJWZkqjSuN3wsVpkzxHgHtF58PcSsSt+3rwWGu/cmc+39jY8NDuVNNGsUU4tczhzYClP5RSObN/+8zPJKtTI/f63QfQJJeZ79FCoQpSVJVfOPHb3kikLbL1Q0zREIVAqY8X+a6hfnrp03zRFP7e6barBHazINJOeyR/RYPursVPavjlsoEIWLCMKyaI4iFKUKwTv+FyHilc+J7+AWYwFXsyc4OtQCDpamu0fVy8apDyjcCp4n+7uMKnGmNE/tVEx7pYJUmj4kETAfLNdqJlQUWBuhlsSUJXyx1AXeOhYh6soQRSlzsePbqFmGxpMjRNrYR07HNnxb/Q3aRALFU7uFBQDrkCscO2MtB3vqoutOL6pwrW9UsVvyHto+bxM7GiUDby/cAShWqVbLZV03ZxPcaFOfNubm5OxxTG/Qt3RyTklYAq+Iwrla1T3H7JliLZjrvlzdpwszZucLtTR6hPQ2yBCr7mP3pCYBgkYqZpRIylhigQq7OwP3HpyUptKdngFhaGETQuN8dUGBYfzWOW/728aGljUg5jbiqEKfk5/x9tUab3lZGGPi+3dfk+Ufsv+IiVWm4lUldEWgWvgZItXO233gzNj8rdpvMMWkB1gFbS9kZ6CtCnMEL+bWXE12XdeQttaiIcZmXM0/Dj7qNhri4UmDhP1GwTOQpSRquQLDdHiYzRH/H7j5+tw3ZBNZ0RxuV5tibQ9wd1PuXiciIswINaCtyD6HSH7YxSsYJn2BB2F9u0bHccmGhAqNjb3ODSc747bfMbqJ8YC4Mp+IoQEcm6zIPXFLbQ8il/VqfQKQg6EnunBG3696c0S4Hrwe03GfqyooXPhlL8BokFgr4gwrnAfIsh2KRuYFygcpfGJogGMLqF9sYa5S+5XVs6J5LHR/rHJFmUGRImIx3dmxsXlu8DShxEop57DHD+slLOljqvgLHS5k6OfiUy3cxS+8/v18jNLc/Z9gIyDesOkvGSGZM2mtxN1m3t6ZAOeEx7GvH8KtjvR+lFdWqM7iTeZHJ7+qOj1wPu4edSdMRL5Tqgx+HxcWx3VXCdCNeSO93MDqnJTZWDUrnk4KfVSpnB+e/aQf3pwLlijZmudaw8xYbKTYnYbqsic0eAAW9l0ZHIFu742Rb9DC0DNvJOijFY9DQtOPIR3CNT12yBdcuhcuEqZoHxgVIYtmYNmN5eHbdjMdiAqGeWaXatlbsYAoWTs+4etBwICWdkjf99X2Z+YgLPrf3AdqhBGndidZ5HYkdWWx2xGBIHbcAnbXdpaWSY5yBBMm5fs4XDiMqAEF2Nlap1dtN700b3m9al0ZL+TzrVp6wrmO5I6N+rlVTvr8vn6/dfeLI+G+WigdO7FF/xXGapp3bdgwPWcYZJVQNDjOR8Nam+NAsJudlEr4QTpr3Blvhj0OsWx+R7UMNvhYgvIoTM9aTkN8tfTiV6TIX6CpdFRmC6sg/ACc6nWjx5IunztDvGjaeUIS5uLETqd8t208/BAIdvTuJHitOgaADUrLj8C/4IjwawzI2o1nqS1d7OPlrKWTJ0NSROkWf6A6zP8C85NoIqCUslwEW3n6Skg/zs3WAWUSnjkiG6znTv2Xy5Gk5/QgCE7BgK19Tqh7R/XUj1PUn8+JcwhgbVogXFWlueSwLqcpZuSevMNl/7Pn+Z8vBOTmFTLeS1gvAepJry4mNEI9WRo5AzJFfqOPYZM5u/2no+jb90S5AxDRDirm6vk2mridrUG/VGUMD1RUxumziGLG8ygq6AnOWasVtiz3aphvWy4DySAoGAlbv90imt3CE7q7SeHxZY+keBWQIHigMNemg+Pt3y5IikE6C51JV15P6+EFFs6AwisH/gnvglMDWK1mSwBDKDHE/bVfDpsXELkf5FvvTUTCl5M2GkDo1kYr3cBftEpMS8O0RMgdITxqY/hZSfokTq73p6DJthMorjvY0tzOM65N8vxE6LlVGF1tJtEciM+I5CXri+YuG1Vm2CX/PILGBLu/RTpem2VK3ozxarL9AgmUmD9TTYhIApzHKhgRm1jHzcyjXBzCh5Wm0c7MSaX2Iu3YoE8JKxT/cmf3gPkFYyLSS58SZ/yrg4v6vAxo9WPjn8xC1OIP7oE1zyVDihUL0FsBdFHOpJXUy/FbvQztwEwJv9JO4x4uYu69myP1RsFnV/vLbABnDGz5jF3+UGpkZ6B/txWI3Xqw8QokJ+VvA37TV42nmE+O5dYt5mWIdEtvPd/VuSsMkBL963xsYzAIf1ohUjoZebrVeU+zNhQTYVAFpUzfnm/E6zsuAgTZ5WfubnzrD3l+ZI/srAjlk3qi5gMcA7Ff6a4iAMdHwxjaNfhPKWudVISBB6dBNwZ1NdXb6u1yTe0wP5NrDGNcL1fe86WyZRSDPrh7Ps1/7OGwVvCVGjhKTg9ktNOWVYj70uOF" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="J4RgOLbzGQyltlj9fw46iRLTPQGnaSemSRdfcR91sfNy4Kz3dtTTaWLj5f+3ZIRqMiy6lYL7RybanwBIskpnGXiD/zCXr4j9JQ6F5m/bjP+9IPGmSFpl0VdGuO1rE3kXjA006Ct7hGtxv+MzgIVNuNcoIvMVW8KzDRWCfO7GXN9LwOyAZTbECYCgG1g3I/GSR1J4Qso8YYE2fp+NmvIa5NWhoxJ5ZDVLukDTKFfGaGyh3h2nq+x0PM1sujZ6FYdgQMSs79YlEAqeb8TDJj0V+TMlTFyzETgEY7deRcpCNP2hz3nnctEALhJuHa11SKgLK6GlrUOL7daigZsud2pK/sbOY3PcnEVcNDzqKfkInA8RvwYL6UDauksEHgAoFEbYzJwyPWU0vhSvVawunRQB7007Wy/6PSyDR7jqVc47DHCaEZeDd/ofPnWFOCliqcD17TzLoNrMeB/1C6OQhLeNH11QP/pYYzQcIkDLr6ng452UXKy0MsmClCMQSCveOc7O4l3krYUhtIg2w3PKtYwNzBwGg4uMpgHAafu74KkpX1yYZ1kwCe2xpMp3QfoxV7Zrr8bJG/qSGE0rEiAQsy0mPlo1nPngkZI5WfhJTG8/6bod4r/rvcdHOsjs7/aLU9gocp+vFF/hqkAQtEKXDNcAi0hlNFUat9d2CVpKHJsGg95sv1Nnv+qODG7y+7udb1Q8ISVjp1tAJl2hdyTwRF3HOOjFhUHc/i0BTT8tTV6k9iQcl+cYnzZj1zzU/zaHJoV7CUTqHCqrqnM0+pot6EMD7zW80u52stJWrdZzsOjYW8CSQyZCw/fyvr6dhARPIk+5OGZrajJlxSPJQ9FQfuAY6lQ7Pt4IybqJ0OCn8CobD7n4ikNjmug4tEg3poTytduWPTnjOFvYpHV/q+BNP4dn9W479tOJJW+S/BfuzpDHR4V20niJ5u9zOFpIQt/dsHci5w66PlPD9RlbUtnOJy0C6Z/XCfT08HhD4SuQX2x8gxWDLTzjVno31uJaViwFqPH18GpGNe0FwvR04iyIfIN1NlWBdjWm/cvLfu5tlLVJ0GOtI2VGhS0mDSywADjMOKfmUPHS85Ybw2GYIg+HjOtMLYtsP75dZh5cwTP1e8uzpUWPBuxysbyY1yC7KsRL7a/Q2zWovysSPQ6r0BcbxoSmmSKZXk9kDV8aUlZa8yuRFzEA59g3Er71DMs2C25/bK/SXvUPgqMYyElXR+bzIKNt6WxGGygidghKqZ6GAWd4+BJfCPh5qOCMkaLdZJ/TidVnHGY3bLAw72EyuWHZVhaZqslRJe8PAyPj+OuUmP/kEdJ5apAfV1WdViiJ9e8t2/pI21w3A5M/rTmmam0gOpuI9ZOlCVm8GZUnqzPl0djiVm6h5+V+C7pBqDSwK3exIqqhwv1kmMZCvDgV7Sbk8Lq1WO6xg3KtqgQBfgfSY2Q7OAvBblmN+c0X1ffwmdLwcelDcBwWfMxKp2ESLhA7Hg8IeAkPh963Q/edrgmhoeY20WJfD0Y31A+ZuoQ6OcNAjtC3N75VfKpYq3Ix2gS0/O2ZGqRTu4qwRwTJ4oOWZvXOnnwtRH2MCcGTMI9nb+Bj2m9sDNtK1jRd/zIirVtFEXYbP3mZ0Daoj2+XJbLB4K9C5lDmps4A4WRPuHBNqKAMfjAdTpEoJB3tRdDwKEEA0A6P0OUY+UEdLnIPRqdbnRYlJs57TwKEYKeY/5g48KMcWveFZrMjxKTMS9eIy+6Iq7lCuPvaJPF6msJkv7ZMwbTQRADvn4joaQTLYOhA4g1M9HG/pNMmgG3EPGIm1bqvKeJA+lyaElWVsdASjWRSnC54W7vBjqun2iCNT95yNPmOpeBd8Yf2YKD8KFePuXhe1eDN6lijQPDrQ8pCLfejMatEzgQduxs9N19V18ic2HzxLjbhDMIxV91mY/jcGNZzlAnfBqMpYdCqik93Jl23OgXV5EY8aE+s2eoF46jngWLxeqoIKwOOa3se4WpcdO+pnT6wuo+fVbqXoP66ynVBxTZ4zwNHqlfHNU+SyqW1Oh84/V6ZXUryLo6VRM6Zlh30L30oLITZdkdicvN5GKBOTp4BjNEn54Semw4XYSfdL4r+fQf/APje0z9S/8shqLH+MderT7xm7zQiEfG2aa4m5V/nTCd6oO3XaZJt0bxmHnmU9C+irwMOzr7Va2VlTG2C2/AcQwRjM8sV5hSJACv6hca6bE6FlcVM98IEV/2zn+1QwOxhJ016/EsEoAGKmzypLpfFaBQIuce/sS3wdDDruI3OPwR0pREbJlfTkmMQ0MuSjYo9ZPPqM7r9G306Lppi26BG0RwIFdJ5wdlkUdbqkHOolQm8BA7ZPT+cvmkAKXVHc4r2uFscOPancJcyhb7h56rvQKq6FvWNudgAyMXFUoaKM9mq8e7N48geT4/V41a0KewYZ0E7sDk+uH/uSmH8bVwkqjX2Qohk9oStYgbOhO36i7nbksvczvWROorVEixp86QjamLT0RwHNT9Kxu1YPgPhh9sdvcK9VIBXtiWM1CEjHWVJX6k4Bxaie0qEZ2BjwA+1v0Ww9TwZvk6KcGqqJDOSixuOyhlbLduFxpsFR3dAGQfM0RJhRyn8SF4deE4DuvkGDqXWGANDQTalprefXVQgQOwX67snBmTgO2mRWVN9dQ4q/zOEsJWagaIIxGeLcVE/TFJogWnTYTCPIBpJ3+LpsA0xNzrRuzOVFGzHOolfsVY12QMcS7bhmOA5dKHsOEkfvIlcasEzmkANz4YthAC+iVD1rYpPp70OGrofYvLF4dEFh3C7HgAAEtkzW35R7tuAYe4dkbaKk9nMzxJKv/eV2k0FeEYhTqlSSssKP9c/EgTBHvBP1d4H1fQPX0z/goCL/MJbsw6rUkJgPDnGuKLnY31+WGaJgDHMbjQCYKYMBO4ufHPWAtemSqLnwVlQljTJxW/S0QJYOXHLBMcDDn24XxFG9FQjlOQKnaPOzINlv/SEKHAZo8KR4cuyBCGCIECDcrjM8jGjrbiI9m/D3otfn07vLhnBrktUN/oXpZRH1UySwrQ0Qmz6r0ycsvPhQxakT1edyrPCtEGj7G6K3Qps3oFgHrSbECUP5roOPHIYyxyWl4/87xEI2GKjB3Kolxp25GdfJdQhhYfn28Uyr6+ii6QcebX5MTMkTWTiN37cjdyRe6mJapR+JAJEiy56eFpCE+XQmjkHa927iaGFjoI41kxnQOf8tEMWulZwLFURNCBWva3Ttk3XDM+oib/JCdW3NUD2qZbAbMho3N0Qrl7QB4+2AHuewpB220O13Q/F7eSqoiBEXHXhO1XOshHc9KM2hlsixrePZfGhSqwRRgKZ5yiYBJhT2DjYE/GBdtjSnrwBpjO5AaLB4uCQXfejBXHW5CNMgD9oiXq4NFTcD15BjwCXbNa/CO1mSWgzxQaF7dgjPwjAX7hAo1L802lCx5EFvxk4RNEQSpoUMhIykU0HKSP2z+MYU/oKGT46WtxvXVa9LfyK6XumAqNbbqw/l5MLBbFAeHAjbrXSIEhvNzN9J6qVbDvbgyzFs6lhVbvfPOnd/qOu5DWXbQU0oG8XbqjuHPBr+8R7Gk7Kdpv6z3I9kn91aVhB3DZzxyKQB4SjiIYChBRMbLfPNlKLXamDqipU+ZLFvkHpRl56orIkAwmq1Cm5r6OEUdELVdtkEt7aZxojjjBFi9jKgn5YpqdBsBqZT8ooogTQ4DFBAAwVkOev3/vZ8PK6kIs2+vPVtRaUyzSYOtI+rpJtaxdRJVx4IR1XFK6G0I682GPxVYgZ/tDuZjYGXNFno6ds2jHeaKFKeRT1GYEmT0m3jpbO0EQJ7kAj/F7Gf95/pjeXJGvIlpA7Oh9QZg84g864uc9G4WQpYGFF6xue2B48XARrJGwb4v2HXV86Bs+UMhLfnf0MiJLOi4IJ0RmgdvYuLj/HfaMRtGqqeT6zR+OmzYNVvkKGlQ6eLu09PxjVa9OiXQ4xMw7kQVS5YOZPEXfkgvcUK3Vk8dqM4L2RZ8wZySTeq19yW5z290J+2rHSeItag1iNUMQ38EZlTg4XbTXk5/i07XKiLHSHledbjqE9Mth8IDRmVLA2XjwIvoo508vbY8ZQhejDIM+s24xOrI/GYlqHRqmkkq1W0oa6GDZiD4omFQl0QZmGtpxadGYMmkM6fR52MUWEqIPFJjZQUV0xTe9yccwvCDanrYW+X4RgVQbJT8T3AEeUVieAZW3kiL/7knGx1B7SfoYkUNn7z8PvTuhPsIgL4I+mrn41QFLqXQsuqwQoIA+nXSGTk0Pw6eoyPksRgbuFUuT+5TA2cO8MgPVnrtyvH5astWjCLAaVw97+2PXJVqP0c72OW1Pcj8M97TrA+gafEBpJb7tAt11csdjOsf5RuBGllfIDNtqJk//jhtQfWiKhxVWe/5zLJwTJfaoO3OWMUq5/JT/dMrVKIDhcgyyIqtQtY9c+" />
</div>
<script type="text/javascript">
@@ -92,497 +106,397 @@ function __doPostBack(eventTarget, eventArgument) { </script>
-<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634981136287450696" type="text/javascript"></script>
+<script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZETFLbdR8wwRMdub1eDU5ILCHE7OhotblLUuaNwx3HQ7rYen0g2&t=635418606520000000" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=ffffffff940d030f" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=ffffffff940d030f" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=VZKNgu1isPaAINPNmSDkniHRmEiR365Y3EPnMj7AXSlsW-OjQIYc7VPoltqjVULZ1g8K9CNDrBJuNvUVOZhFqH3NS7yTvcU3NnCeS_FcC9dLDDQ8Q9UH7PW6s-B2gF04VAooHH3Ji69sDY7LPmffv0PShiGc1206s_RLAIzuI952BGa9reXAmYClCuFJH4FjsvPZoM7oG82eR9HPyOS28x0KmiQ1" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=H0ET7B4U8EJwmcAbxjSGxSsqhUYAPJWkcrAuejTBaZ7N1SX_jc3D8QuNKUPa0lO4X3QHb4S3pibvaKNYs1ChjXro9ahCfiZGcYIQu6Ypce_q7YOm_PkXbcyD93f6aDlH4D9eFkkuLiE9Ax4WQgrrygMqipqtLqR7mio-gp6w-ttXgLxtrsFRt-pUjltSCvHgWUwBtVr9wTSTuzeTLswFqWhBmRPpN7g52pLMsR4cwsSOiAKUeb6dRJ_DZWWUA7Gz0XyQM93WLdA3NKoaC8qUufQM3ZOa5RAudzueB87VFLfeuhZXxK1-AsHyrJkHMiOGwGZjN55yCPtP1BEwdRcWpCJwU7Y_efv4APmLdYZJuvt4AxhKqZdv9FBT2n8FSDrgUdJXxmOVf_5r2_lt_khWegXBwRoygGjD3nKfQf8Q-zpyIsJZZDzQ8Td_2c9eDB4Zy1LRk5dNsNZy6hAaWo_Uq50DOnrNf0LY0qwB1ZAd9b-kZLlEUQjaCXSSBeCccOLbgDalKaxQ15-fEh-R_Lqgt1720fRQyzlevhgNz5vknnm2hF_vHLKlKAoJWuuSIFEiIgEz-JeplpCgAtzjjo0mJ2Zdl9v_fAQxwE4XgBXmUTaiSmoT6TxPHJPr-3BmMQSZs2qBNbYrFu53gs5JbsKPA0pdzyHLlfP2bYUDBdjB1oCqq5qW0" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=uHIkleVeDJf4xS50Krz-yEJRbXY2x1dOBEdM7W-QkNpgaumdwaefPzMErSeG_W29-lHX6vl5G7uDafHaYWCx8Z9aLlo8tZwVtV42ISp6LhT6LbxuVUWMo5GyApWAyPOqkSkf1vCyntgT-PmPv-C6FWxsbWo1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=Jw6tUGWnA15YEa3ai3FadDbNvwkajNGIHz7aGm4w_MLRMuZ5hwlk3bfOsTs3E4cZZ4ktnTFE_MzciTx4exD15JXabrPKGazf6xj6fW1A8vXJoc3OCqf4cg_BDlVl8fQEsQiziDh4kHnJRWZEQotwuLoezlg1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=LsSN37T_JTo8WmXc7IWe9h7QNKB5hH17UtyHRfQt428U3aulvj53CANg-qZVzIBuh0jojGRwyA5u6DVnEet85JW-JpWduEGLE0VE-2wGHR4yu7MNj7XtsTLWd21Jk8RZENZmygJcHOHGMS1oisYKTWQSIQA1" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=VUtFLQIK94pF36sSxa5M5Q4KyVgkk4aq_Lj3yxNWv9FE_GBcdEQWlyUYzpoPTO27D4G7EbYHTqxoW35XPdin3tebmTxp-wSfJzzK8-nJzs2HapzFx4fuNPR6OjDBQmtyWLMl9s_v9cfV2Mm7C3dG-PYITU2UMwNSjAESeyXFqfw8frZJE2LykLAMOmhcIMdVDEZ3towfhsTqOSZWPCdiMeHylJ16anMqLsL7z0oT5vyUbvIiPYHpYKrAEJIDFxritjPVOv9orjoRf-8NlzG0PwzvCPCUNUOn0q725aaI6lCODxhDBiPw-ciHHQzmbbGdaID-mnjIV9nX6-dgUyOpCAzwZXAoBQPQ6TU3GjtYmetglM7I31meDWRS7sDj-e3m--4pB0SzCNbw9t_ZQ6DjARVQyTvBJksCHM-RcfVHoBtuq9rOTWynsJGmm_Lg2JD7o-KVYJOAuPGcUEcNWxswz-cLWquZQ3_vABHJxAaFz-lnYYwzEyEWn9I2tPIwXjHtZVAB3g0G-dsEEFKNFYXpU1N0r25KNq4NEKXKQg1QI99Bxq6sUV0UkKPNGk0f24VH7_RXyG7L9I3rXDfYaVq1X300crsUh2Cn0-mUkdpiqhtb63KB_jWzXr9HEzeR_socdD-U_PhMKdYigWqerk55eRcMsVPuiRN1yBkFE3GQiZawEqjI0" type="text/javascript"></script>
<script src="../seek/js/cachedetails.js" type="text/javascript"></script>
<script src="../js/latlng.js" type="text/javascript"></script>
- <script type="text/javascript">
+<div>
+
+ <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="C05D5804" />
+</div>
+ <script type="text/javascript">
//<![CDATA[
Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
//]]>
</script>
- <div id="Top" class="SkipLinks">
- <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
- <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
- </div>
- <!--[if lte IE 7]>
- <div class="WarningMessage PhaseOut">
- <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
- </div>
- <![endif]-->
-
-
- <div class="PrintOnly">
- <p>
- <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
- </p>
- <hr />
- </div>
- <header id="ctl00_siteHeader">
- <div class="container">
- <h1 class="Logo span-16">
- <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
- <img src="/images/tlnMasters/geocaching-logo.png" alt="Geocaching" height="43" width="301" />
- </a>
- </h1>
- <div class="ProfileWidget span-8 last">
-
- <div id="ctl00_divSignedIn">
- <p class="Avatar NoBottomSpacing">
- <a id="ctl00_hlHeaderAvatar" accesskey="p" title="Your Profile" href="../my/"><img title="Your Profile" src="http://img.geocaching.com/user/avatar/e8a97a05-a051-4da9-bc93-6a830b866aff.jpg" alt="" style="border-width:0px;" /></a>
- </p>
- <p class="SignedInText">
- <strong>
- Hello, <a href="/my/default.aspx" title="View Profile for JoSaMaJa" class="SignedInProfileLink">JoSaMaJa</a></strong> (<a id="ctl00_hlSignOut" accesskey="s" title="Sign Out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC1ZXX2%26title%3dhannopoly-eislisenstrasse%26Submit6%3dGo">Sign Out</a>)<br />
- <span id="ctl00_litPMLevel">Premium Member</span>
-
- <strong style="display: block">
- 484 Caches Found</strong>
-
- </p>
- </div>
- </div>
- </div>
- </header>
- <nav id="Navigation">
- <div class="container">
- <ul class="Menu">
- <li>
- <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li>
- <li>
- <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Geocaching in 2 Minutes</a></li>
- </ul>
- </li>
-
- <li id="ctl00_liNavProfile">
- <a id="ctl00_hlNavProfile" accesskey="2" title="Your Profile" href="../my/">Your Profile ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavQuickView" accesskey="p" title="Quick View" href="../my/">Quick View</a></li>
- <li>
- <a id="ctl00_hlSubNavLists" accesskey="q" title="Lists" href="../my/lists.aspx">Lists</a></li>
- <li class="ExtraText">
- <a id="ctl00_hlSubNavGeocaches" accesskey="m" title="Geocaches" class="NoRightPadding" href="../my/geocaches.aspx">Geocaches</a>
- (<a id="ctl00_hlSubNavGeocachesYours" accesskey="y" title="Your Geocaches" class="NoSidePadding" href="../my/owned.aspx">Yours</a>)</li>
- <li class="ExtraText">
- <a id="ctl00_hlSubNavProfileTrackables" title="Trackables" class="NoRightPadding" href="../my/travelbugs.aspx">Trackables</a>
- (<a id="ctl00_hlSubNavTrackablesYours" accesskey="8" title="Your Trackables" class="NoSidePadding" href="../track/search.aspx?o=1&uid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">Yours</a>)</li>
- <li>
- <a id="ctl00_hlSubNavPocketQueries" accesskey="9" title="Pocket Queries" href="../pocket/">Pocket Queries</a></li>
- <li>
- <a id="ctl00_hlSubNavFieldNotes" accesskey="0" title="Field Notes" href="../my/fieldnotes.aspx">Field Notes</a></li>
- <li>
- <a id="ctl00_hlSubNavAccount" accesskey="a" title="Account Details" href="../account/">Account Details</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="../seek/">Play ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="../seek/">Hide & Seek a Cache</a></li>
- <li>
- <a id="ctl00_hlSubNavLogCache" title="Log a Cache" href="../my/recentlyviewedcaches.aspx">Log a Cache</a></li>
- <li>
- <a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li>
- <li>
- <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="../track/">Find Trackables</a></li>
- <li>
- <a id="ctl00_hlSubNavGeoTours" title="GeoTours" href="../adventures/geotours">GeoTours</a>
- </li>
- <li>
- <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a>
- <ul class="SubMenu">
-
- <li>
- <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a>
- </li>
-
- <li>
- <a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li>
- <li>
- <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li>
- <li>
- <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
- <li>
- <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
- <li>
- <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop Geocaching</a></li>
- <li>
- <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
- <li>
- <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li>
- <li>
- <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li>
- <li>
- <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li>
- <li>
- <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li>
- <li>
- <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li>
- <li>
- <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li>
- <li>
- <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/geocaching">Follow Us ▼</a>
- <ul class="SubMenu NavSocialMedia">
- <li>
- <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/geocaching">Facebook</a></li>
- <li>
- <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li>
- <li>
- <a id="ctl00_hlSubNavInstagram" title="Instagram" class="SubNavInstagram" href="http://instagram.com/gogeocaching">Instagram</a></li>
- <li>
- <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li>
- </ul>
- </li>
- </ul>
- <div class="LanguageSelector">
-
-
-<div class="LocaleText">
-
- <strong>Choose Your Language:</strong>
-
-</div>
-<div class="LocaleList">
-
- <div class="selected-language">
-
- <a href="#">English▼</a>
-
- </div>
- <ul class="language-list">
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Latviešu</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, Bokmål</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li>
-
- </ul>
-
-</div>
-<script type="text/javascript">
-
- jQuery(document).ready(function () {
- jQuery(".selected-language a").click(function (e) {
- e.preventDefault();
- var $loc = jQuery(this).parent().next();
- jQuery($loc).show().position({
- of: $loc.parent(),
- my: "left top",
- at: "left bottom",
- offset: "0 0",
- collision: "fit fit"
- });
- jQuery(this).addClass("Expanded");
- jQuery(document).click(function () {
- jQuery(".language-list").fadeOut("fast");
- jQuery(".selected-language a").removeClass("Expanded");
- });
- return false;
- });
- });
-</script>
- </div>
+ <div id="Top" class="SkipLinks">
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
</div>
- </nav>
- <section id="Content">
+ <!--[if lte IE 8]>
+ <div class="WarningMessage PhaseOut">
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+ </div>
+ <![endif]-->
- <div class="container">
- <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
- <p>
- <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
- </p>
-
- </div>
- <div id="ctl00_divContentMain" class="span-24 last">
-
-
-
- <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
-
- <p>
- <a href="#" class="CoordInfoLink">
- <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC1ZXX2</span>
- <span class="arrow">▼</span> </a>
- </p>
-
-</div>
-<div id="dlgClipboard">
- <input type="text" class="TextFormat" />
- <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close">
- x</a>
-</div>
-<script type="text/javascript">
- $("a.CoordInfoLink").click(function (e) {
- e.preventDefault();
-
- $("#dlgClipboard")
- .show()
- .position({
- of: $("a.CoordInfoLink"),
- my: "right top",
- at: "right bottom",
- offset: "0 5"
- })
- .find("input")
- .val('http://coord.info/' + $('.CoordInfoCode').text())
- .focus()
- .select();
-
- $(document).mouseup(function (e) {
- if ($(e.target).parent("div#dlgClipboard").length == 0) {
- $(this).unbind(e);
- $("div#dlgClipboard").hide();
- }
- });
-
- return false;
- });
-
-
-</script>
-
- <div class="span-17">
- <div class="span-17 last BottomSpacing" id="cacheDetails">
- <p class="cacheImage">
- <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/2.gif" alt="Traditional Cache" title="Traditional Cache" /></a>
- </p>
-
- <h2 class="NoBottomSpacing">
- <span id="ctl00_ContentBody_CacheName">Hannopoly: Eislisenstrasse </span>
- </h2>
- <div class="minorCacheDetails Clear">
- <div id="ctl00_ContentBody_mcd1">
- A cache by <a href="http://www.geocaching.com/profile/?guid=8186d342-6f46-4d9e-8ba3-2e7b51426798&wid=36d45871-b99d-46d6-95fc-ff86ab564c98&ds=2">Rich Uncle Pennybags </a>
- </div>
- <div id="ctl00_ContentBody_mcd2">
- Hidden
- :
- 2009-10-16
-
- </div>
- <div>
-
- </div>
- </div>
- </div>
- <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-6 BottomSpacing">
-
- <dl>
- <dt>
- Difficulty:</dt>
- <dd>
- <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars3.gif" alt="3 out of 5" /></span>
- </dd>
- </dl>
- <dl>
- <dt>
- Terrain:</dt>
- <dd>
- <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars1_5.gif" alt="1.5 out of 5" /></span>
- </dd>
- </dl>
-
- </div>
- <div id="ctl00_ContentBody_size" class="CacheSize span-5">
-
- <p class="AlignCenter">
- Size: <span class="minorCacheDetails"><img src="/images/icons/container/other.gif" alt="Size: other" title="Size: other" /> <small>(other)</small></span>
+ <div class="PrintOnly">
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
</p>
-
+ <hr />
</div>
- <div class="span-6 right last">
-
-
- <div class="favorite right">
- <a id="uxFavContainerLink" href="javascript:void(0);">
- <div class="favorite-container"><!-- TODO! -->
- <span class="favorite-value">
- 42
- </span>
- Favorites
- </div>
+ <header id="ctl00_siteHeader">
+ <div class="container">
+ <h1 class="Logo">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
</a>
- <div class="favorite-dropdown">
-
- <ul>
- <li>
- <img id="imgFavoriteScore" src="/images/loading3.gif" width="20" height="20" alt="Loading" title="Loading"><span id="uxFavoriteScore"> </span>
- </li>
- <li>
- <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="/seek/cache_favorited.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View Who Favorited this Cache</a>
+ </h1>
+ <div class="ProfileWidget">
+
+ <div id="ctl00_divSignedIn">
+ <ul class="logged-in-user">
+ <li class="li-user">
+ <a class="SignedInProfileLink" href="/my/default.aspx" title="View Your Profile">
+ <span class="avatar">
+ <img id="ctl00_hlHeaderAvatar" src="https://img.geocaching.com/avatar/642d2771-424e-4ee6-beb6-efecde3406fc.jpg" style="border-width:0px;" />
+ </span>
+ <span class="li-user-info">
+ <span>Bananeweizen</span>
+ <span class="cache-count">743 Finds</span>
+ </span>
+ </a>
+ <button type="button" class="li-user-toggle">
+ <svg width="12px" height="7px" viewBox="0 0 12 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g class="arrow" transform="translate(-1277.000000, -25.000000)" stroke="#FFFFFF" fill="#FFFFFF">
+ <path d="M1280.43401,23.3387013 C1280.20315,23.5702719 1280.20315,23.945803 1280.43401,24.1775793 L1284.82138,28.5825631 L1280.43401,32.9873411 C1280.20315,33.2191175 1280.20315,33.5944429 1280.43401,33.8262192 C1280.54934,33.9420045 1280.70072,34 1280.8519,34 C1281.00307,34 1281.15425,33.9422102 1281.26978,33.8262192 L1286.07462,29.0018993 C1286.30548,28.7701229 1286.30548,28.3947975 1286.07462,28.1630212 L1281.26958,23.3387013 C1281.03872,23.106925 1280.66487,23.106925 1280.43401,23.3387013 Z" id="Dropdown-arrow" sketch:type="MSShapeGroup" transform="translate(1283.254319, 28.582435) scale(1, -1) rotate(-90.000000) translate(-1283.254319, -28.582435) "></path>
+ </g>
+ </g>
+ </svg>
+ </button>
+ <ul>
+ <li class="li-settings">
+ <a title="Edit Account Settings" class="icon-settings" href="/account/settings">Settings</a>
+ </li>
+ <li class="li-signout">
+ <a id="ctl00_hlSignOut" accesskey="s" class="sign-out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC1ZXX2%26title%3dhannopoly-eislisenstrasse">Sign Out</a>
+ </li>
+ </ul>
+ </li>
+ <li class="li-messagecenterheaderwidget li-messages" id="messagecenterheaderwidget">
+ <a class="message-center-icon" href="/account/messagecenter">
+ <span class="msg-center-link-text">Messages</span>
+ </a>
</li>
- <li>
- <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a>
+ <li class="li-upgrade">
+
+
</li>
</ul>
</div>
</div>
-
-
- </div>
-
- <p class="Clear">
-
-
- </p>
-
- <p class="OldWarning NoBottomSpacing"><strong>Cache Issues:</strong></p><ul class="OldWarning"><li>This cache has been archived, but is available for viewing for archival purposes.</li></ul>
-
- <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable">
- <div class="LocationData FloatContainer">
- <div class="span-9">
- <p class="NoBottomSpacing">
- <a href="#" class="edit-cache-coordinates" id="uxLatLonLink" title="Correct these coordinates">
- <strong>
- <span id="uxLatLon">N 52° 22.393 E 009° 42.648</span></strong>
- </a>
- <br />
- <span id="ctl00_ContentBody_LocationSubPanel">
- UTM: 32U E 548389 N 5802787<br />
- </span>
- <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="/wpt/?lat=52.373217&lon=9.7108&detail=1" target="_blank">Other Conversions</a>
- </p>
- </div>
- <div class="span-7 last AlignRight">
- <span id="ctl00_ContentBody_Location">In Niedersachsen, Germany</span><br />
- <span id="lblDistFromHome"><img src="/images/icons/compass/N.gif" alt="N" style="vertical-align:text-bottom" /> N 17.5 km from your home location</span>
- </div>
</div>
- <div class="DownloadLinks">
- <dl id="Print">
- <dt class="label">
- <span id="ctl00_ContentBody_uxPrintHeader">Print</span>:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98" target="_blank">No Logs</a>
- <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&lc=5" target="_blank">5 Logs</a>
- <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&lc=10" target="_blank">10 Logs</a>
- <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=52.21625,9.714483 (Home Location)&daddr=52.373217,9.7108(Hannopoly%3a+Eislisenstrasse+)" target="_blank">Driving Directions</a>
- </dd>
- </dl>
- <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;">
- <dt>
- PDF:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a>
- <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a>
- <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a>
- </dd>
- </dl>
- <dl id="Download">
- <dt class="label">
- <span id="ctl00_ContentBody_uxDownloadLabel">Download</span>:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="/software/default.aspx">Read about waypoint downloads</a>
- </dd>
- <dt></dt>
- <dd>
- <input type="submit" name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" /><input type="submit" name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" /><input type="submit" name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('36d45871-b99d-46d6-95fc-ff86ab564c98');return false;" id="ctl00_ContentBody_btnSendToGPS" /><input type="submit" name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC1ZXX2');return false;" id="ctl00_ContentBody_btnSendToPhone" />
- </dd>
- </dl>
- </div>
- </div>
-
- <div class="Note Disclaimer">
- <strong>
- Please note
- </strong>
- Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>.
- </div>
-
-
- <div class="Note PersonalCacheNote">
- <strong>
- Personal Cache Note
- </strong>
- <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" />
- <span id="cache_note">
-
- </span>
+ </header>
+ <nav id="Navigation">
+ <div class="container">
+ <a href="../" id="ctl00_A1" class="Logo" title="Geocaching" accesskey="h">
+ <img src="/images/tlnMasters/logo-geocaching@2x.png" alt="Geocaching" width="195" />
+ </a>
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" class="Dropdown" href="../guide/">Learn</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Videos</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="2" class="Dropdown" href="../play/search/">Play</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavFind" accesskey="d" href="../play/search/">Find a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" href="../play/hide/">Hide a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavMap" accesskey="/" href="../map/">View Geocache Map</a></li>
+ <li id="ctl00_liSubNavLogCache">
+ <a id="ctl00_hlSubNavLogCache" href="../my/recentlyviewedcaches.aspx">Log a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" href="../track/">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeoTours" href="../play/geotours">GeoTours</a>
+ </li>
+ <li id="ctl00_liSubNavPocketQueries">
+ <a id="ctl00_hlSubNavPocketQueries" accesskey="9" href="../pocket/">Pocket Queries</a></li>
+ <li id="ctl00_liSubNavFieldNotes">
+ <a id="ctl00_hlSubNavFieldNotes" accesskey="0" href="../my/fieldnotes.aspx">Field Notes</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="3" class="Dropdown" href="../forums/">Community</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" href="../account/referafriend">Refer a Friend</a>
+ </li>
+
+ <li>
+ <a id="ctl00_hlSubNavVolunteers" accesskey="+" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" class="Dropdown" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">USA Shop</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlBecomePremium" href="https://payments.geocaching.com/?upgrade=true">Become a Premium Member</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
</div>
-
- <h3 class="CacheDescriptionHeader">Geocache Description:</h3>
- <div class="UserSuppliedContent">
+ </nav>
+ <section id="Content">
+ <div class="container">
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+ <!--<p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
+ </p>-->
+
+ </div>
+ <div id="ctl00_divContentMain" class="span-24 last">
+ + + + <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
+ + <p> + <a href="#" class="CoordInfoLink"> + <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC1ZXX2</span> + <span class="arrow">▼</span> </a> + </p> +
+</div> +<div id="dlgClipboard"> + <input type="text" class="TextFormat" /> + <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close"> + x</a> +</div> +<script type="text/javascript"> + $("a.CoordInfoLink").click(function (e) { + e.preventDefault(); + + $("#dlgClipboard") + .show() + .position({ + of: $("a.CoordInfoLink"), + my: "right top", + at: "right bottom", + offset: "0 5" + }) + .find("input") + .val('http://coord.info/' + $('.CoordInfoCode').text()) + .focus() + .select(); + + $(document).mouseup(function (e) { + if ($(e.target).parent("div#dlgClipboard").length == 0) { + $(this).unbind(e); + $("div#dlgClipboard").hide(); + } + }); + + return false; + }); + + +</script> + + + <div class="span-17"> + + <div class="span-17 last BottomSpacing" id="cacheDetails"> + <p class="cacheImage"> + <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/2.gif" alt="Traditional Geocache" title="Traditional Geocache" /></a> + </p> + + <h2 class="NoBottomSpacing"> + <span id="ctl00_ContentBody_CacheName">Hannopoly: Eislisenstrasse </span> + </h2> + <div class="minorCacheDetails Clear"> + <div id="ctl00_ContentBody_mcd1"> + A cache by <a href="http://www.geocaching.com/profile/?guid=8186d342-6f46-4d9e-8ba3-2e7b51426798&wid=36d45871-b99d-46d6-95fc-ff86ab564c98&ds=2">Rich Uncle Pennybags </a> + </div> + <div id="ctl00_ContentBody_mcd2"> + Hidden + : + 2009-10-16 + + </div> + <div> + + </div> + </div> + </div> + <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-6 BottomSpacing"> + + <dl> + <dt> + Difficulty:</dt> + <dd> + <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars3.gif" alt="3 out of 5" /></span> + </dd> + </dl> + <dl> + <dt> + Terrain:</dt> + <dd> + <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars1_5.gif" alt="1.5 out of 5" /></span> + </dd> + </dl> + + </div> + <div id="ctl00_ContentBody_size" class="CacheSize span-5"> + + <p class="AlignCenter"> + Size: <span class="minorCacheDetails"><img src="/images/icons/container/other.gif" alt="Size: other" title="Size: other" /> <small>(other)</small></span> + </p> + + </div> + <div class="span-6 right last"> + + + <div class="favorite right"> + <a id="uxFavContainerLink" href="javascript:void(0);"> + <div class="favorite-container"><!-- TODO! --> + <span class="favorite-value"> + 41 + </span> + Favorites + </div> + </a> + <div class="favorite-dropdown"> + + <ul> + <li> + <img id="imgFavoriteScore" src="/images/loading3.gif" width="20" height="20" alt="Loading" title="Loading"><span id="uxFavoriteScore"> </span> + </li> + <li> + <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="/seek/cache_favorited.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View Who Favorited this Cache</a> + </li> + <li> + <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a> + </li> + </ul> + </div> + </div> + + + </div> + + <p class="Clear"> + + + + </p> + + <p class="OldWarning NoBottomSpacing"><strong>Cache Issues:</strong></p><ul class="OldWarning"><li>This cache has been archived, but is available for viewing for archival purposes.</li></ul> + + <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable"> + <div class="LocationData FloatContainer"> + <div class="span-9"> + <p class="NoBottomSpacing"> + <a href="#" class="edit-cache-coordinates" id="uxLatLonLink" title="Correct these coordinates"> + <strong> + <span id="uxLatLon">N 52° 22.393 E 009° 42.648</span></strong> + </a> + <br /> + <span id="ctl00_ContentBody_LocationSubPanel"> + UTM: 32U E 548389 N 5802787<br /> + </span> + <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="/wpt/?lat=52.373217&lon=9.7108&detail=1" target="_blank">Other Conversions</a> + </p> + </div> + <div class="span-7 last AlignRight"> + <span id="ctl00_ContentBody_Location">In Niedersachsen, Germany</span><br /> + <span id="lblDistFromHome"><img src="/images/icons/compass/N.gif" alt="N" style="vertical-align:text-bottom" /> N 392.3 km from your home location</span> + </div> + </div> + <div class="DownloadLinks"> + <dl id="Print"> + <dt class="label"> + <span id="ctl00_ContentBody_uxPrintHeader">Print</span>: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98" target="_blank">No Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&lc=5" target="_blank">5 Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&lc=10" target="_blank">10 Logs</a> + <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=48.861002,9.186577 (Home Location)&daddr=52.373217,9.7108(Hannopoly%3a+Eislisenstrasse+)" target="_blank">Driving Directions</a> + </dd> + </dl> + <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;"> + <dt> + PDF: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a> + <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a> + <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a> + </dd> + </dl> + <dl id="Download"> + <dt class="label"> + <span id="ctl00_ContentBody_uxDownloadLabel">Download</span>: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="/software/default.aspx">Read about waypoint downloads</a> + </dd> + <dt></dt> + <dd> + <input type="submit" name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" /><input type="submit" name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" /><input type="submit" name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('36d45871-b99d-46d6-95fc-ff86ab564c98');return false;" id="ctl00_ContentBody_btnSendToGPS" /><input type="submit" name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC1ZXX2');return false;" id="ctl00_ContentBody_btnSendToPhone" /> + </dd> + </dl> + </div> + </div> + + <div class="Note Disclaimer"> + <strong> + Please note + </strong> + Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>. + </div> + + + <div class="Note PersonalCacheNote"> + <strong> + Personal Cache Note + </strong> + <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" /> + + <span id="cache_note"></span> + </div> + + <h3 class="CacheDescriptionHeader">Geocache Description:</h3> + <div class="UserSuppliedContent"> + <span id="ctl00_ContentBody_ShortDescription">
-</span>
-
- </div>
-
- <br />
- <div class="UserSuppliedContent">
-
+</span> + + </div> + + <br /> + <div class="UserSuppliedContent"> + <span id="ctl00_ContentBody_LongDescription"><center><img width="500" src="http://img.geocaching.com/cache/5df239fe-92ea-4f18-ad9d-35910cfa5ea3.jpg" border="0" /><br />
<br />
<table width="510" border="0" cellpadding="0" cellspacing="0" align="center">
@@ -637,609 +551,544 @@ Man weiß hier Bescheid. Dieser Cache ist rund um die Uhr zu finden, ohne ein Ge <td colspan="3" rowspan="1" bgcolor="#000000" width="498" height="2"></td>
</tr>
</table>
-</center></span>
-
- </div>
-
- <p>
-
-
- </p>
- <p id="ctl00_ContentBody_hints">
- <strong>
- Additional Hints</strong>
- (<a id="ctl00_ContentBody_lnkDH" title="Decrypt" onclick="return false;" href="../seek/#">No hints available.</a>) </p><div id="div_hint" class="span-8 WrapFix">
- </div><div id='dk' style="display: block;" class="span-9 last">
- <span id="ctl00_ContentBody_EncryptionKey" class="right"></span>
- </div>
- <div class="Clear">
- </div>
-
- </div>
-
-
- <div class="span-6 prepend-1 last">
-
-
-<div class="CacheDetailNavigation NoPrint">
-
- <a href="/seek/log.aspx?ID=1433909&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log your visit</a>
- <ul>
- <li><a href="/seek/gallery.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View Gallery</a> (2)</li>
- <li><a href="/my/watchlist.aspx?w=1433909">Watch</a> (5)</li>
- <li><a href="/bookmarks/mark.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&WptTypeID=2">Bookmark</a></li>
- <li><a href="/bookmarks/ignore.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&WptTypeID=2">Ignore</a></li>
- </ul>
-
-</div>
-
-
-
-
- <div id="map_preview_canvas" class="TopSpacing" style="width: 228px; height: 175px;">
- </div>
-
-
-
- <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing">
-
- <h3 class="WidgetHeader">
- Attributes
- </h3>
- <div class="WidgetBody">
- <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/stroller-yes.gif" alt="stroller accessible" title="stroller accessible" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/kids-yes.gif" alt="kid friendly" title="kid friendly" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p>
- </div>
-
- </div>
-
-
+</center></span> + + </div> + + <p> + + + </p> + <p id="ctl00_ContentBody_hints"> + <strong> + Additional Hints</strong> + (<a id="ctl00_ContentBody_lnkDH" title="Decrypt" onclick="return false;" href="../seek/#">No hints available.</a>) </p><div id="div_hint" class="span-8 WrapFix"> + </div><div id='dk' style="display: block;" class="span-9 last"> + <span id="ctl00_ContentBody_EncryptionKey" class="right"></span> + </div> + <div class="Clear"> + </div> + + </div> + + + <div class="span-6 prepend-1 last"> + + +<div class="CacheDetailNavigation NoPrint"> + + <a href="/seek/log.aspx?ID=1433909&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log your visit</a> + <ul> + <li><a href="/seek/gallery.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View Gallery</a> (2)</li> + <li><a href="/my/watchlist.aspx?w=1433909">Watch</a> (5)</li> + <li><a href="/bookmarks/mark.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&WptTypeID=2">Bookmark</a></li> + <li><a href="/bookmarks/ignore.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&WptTypeID=2">Ignore</a></li> + </ul> + + +</div> + + + + + <div id="map_preview_canvas" class="TopSpacing" style="width: 228px; height: 175px;"> + </div> + + + + <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing"> + + <h3 class="WidgetHeader"> + Attributes + </h3> + <div class="WidgetBody"> + <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/stroller-yes.gif" alt="stroller accessible" title="stroller accessible" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/kids-yes.gif" alt="kid friendly" title="kid friendly" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p> + </div> + + </div> + + <div id="ctl00_ContentBody_uxBanManWidget" class="InlinePageAds">
-
-
+ + <script type='text/javascript'>
googletag.cmd.push(function() {{
-googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_3e84a16e-f845-4110-9c69-8f95e1834036').addService(googletag.pubads());
+googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_6c41dce1-3789-48e2-9686-3a8b50c1d3ba').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
}});
</script>
-<div id='div_3e84a16e-f845-4110-9c69-8f95e1834036'>
+<div id='div_6c41dce1-3789-48e2-9686-3a8b50c1d3ba'>
<script type='text/javascript'>
-googletag.cmd.push(function() { googletag.display('div_3e84a16e-f845-4110-9c69-8f95e1834036'); });
+googletag.cmd.push(function() { googletag.display('div_6c41dce1-3789-48e2-9686-3a8b50c1d3ba'); });
</script>
</div>
-
- <p>
+ + <p> <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small> </p>
-</div><div class="GoogleAds AlignCenter BottomSpacing">
-
- </div>
- <div class="clear">
- </div>
-
- <span id="ctl00_ContentBody_lnkTravelBugs"></span>
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">
- <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span>
- </h3>
- <div class="WidgetBody">
-
-
+</div><div class="GoogleAds AlignCenter BottomSpacing"> + + </div> + <div class="clear"> + </div> + + <span id="ctl00_ContentBody_lnkTravelBugs"></span> + + +<div class="CacheDetailNavigationWidget"> + + <h3 class="WidgetHeader"> + <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span> + </h3> + <div class="WidgetBody"> + + <div id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItems">
-
- <p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p>
-
-</div>
- <div class="TopSpacing">
-
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=36d45871-b99d-46d6-95fc-ff86ab564c98">View past Trackables</a></p>
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p>
- </div>
-
-
- </div>
-
-
-</div>
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">Bookmark Lists</h3>
- <div class="WidgetBody">
-
-
- <ul class="BookmarkList">
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=41cd56b6-00f1-4702-b866-1a268c649d13">Alle Hannopoly Caches</a><br /> by <a href="http://www.geocaching.com/profile/?guid=df2184ab-a9ea-4d30-98ed-ec4e851c3706">Gummiseele</a>
- </li>
-
- <li class='AlternatingRow'>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=0dcf3f86-9372-499c-8b57-ed419bd48e21">Meine Empfehlung</a><br /> by <a href="http://www.geocaching.com/profile/?guid=c46541fc-6ae9-4452-8833-470ddfbe9cee">skrell</a>
- </li>
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=9a248db9-3063-4457-9205-851fbe06a03e">Hannopoly</a><br /> by <a href="http://www.geocaching.com/profile/?guid=5c4b0915-5cec-4fa1-8afd-4b3ca67e004e">kai2707</a>
- </li>
-
- </ul>
-
- <p class="NoBottomSpacing">
- <a href="/bookmarks/default.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&WptTypeID=2" title="View all 6 bookmark lists...">View all 6 bookmark lists...</a>
- </p>
-
- </div>
-
-
-</div>
-
-
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">My Bookmark Lists</h3>
- <div class="WidgetBody">
-
-
- <ul class="BookmarkList">
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=14551708-0c3c-4f95-9342-1bb3119e6efe">cgeo mocks</a><br /> by <a href="http://www.geocaching.com/profile/?guid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">JoSaMaJa</a>
- </li>
-
- </ul>
-
- <p class="NoBottomSpacing">
-
- </p>
-
- </div>
-
-
-</div>
-
-
-
-
- </div>
-
-
- <div id="ctl00_ContentBody_bottomSection" class="span-24 last">
-
- <p>
- <br />
-
-
- <p>
+ + <p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p> +
+</div> + <div class="TopSpacing"> + + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=36d45871-b99d-46d6-95fc-ff86ab564c98">View past Trackables</a></p> + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p> + </div> + + + </div> + + +</div> + + +<div class="CacheDetailNavigationWidget"> + <h3 class="WidgetHeader"> + Bookmark Lists + </h3> + <div class="WidgetBody"> + + <ul class="BookmarkList"> + + <li class=''> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=41cd56b6-00f1-4702-b866-1a268c649d13">Alle Hannopoly Caches</a><br />by <a href="http://www.geocaching.com/profile/?guid=df2184ab-a9ea-4d30-98ed-ec4e851c3706">Gummiseele</a> + </li> + + <li class='AlternatingRow'> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=0dcf3f86-9372-499c-8b57-ed419bd48e21">Meine Empfehlung</a><br />by <a href="http://www.geocaching.com/profile/?guid=c46541fc-6ae9-4452-8833-470ddfbe9cee">skrell</a> + </li> + + <li class=''> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=9a248db9-3063-4457-9205-851fbe06a03e">Hannopoly</a><br />by <a href="http://www.geocaching.com/profile/?guid=5c4b0915-5cec-4fa1-8afd-4b3ca67e004e">kai2707</a> + </li> + + </ul> + + <p class="NoBottomSpacing"> + <a href="/bookmarks/default.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98&WptTypeID=2" title="View all 6 bookmark lists...">View all 6 bookmark lists...</a> + </p> + </div> +</div> + + + + + </div> + + + <div id="ctl00_ContentBody_bottomSection" class="span-24 last"> + + <p> + <br /> + + + <p> <div id="uxlrgMap" class="FloatRight TopSpacing">
-
- <div class="PageBreakBefore">
-
- </div>
- <div class="CDMapWidget">
- <p class="WidgetHeader NoBottomSpacing">
- <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="/map/default.aspx?lat=52.373217&lng=9.7108" target="_blank">View Larger Map</a>
- </p>
-
- <div id="map_canvas" style="width: 325px; height: 325px;">
- </div>
- <p class="WidgetFooter">
- <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a>
- </p>
- </div>
- <div style="display: none;">
- <div id="mapPrintingNotes">
- To print the map in Firefox and Opera, enable background images in the print dialog.
- <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()">
- Close
- </a>
- </div>
- </div>
+ + <div class="PageBreakBefore"> + + </div> + <div class="CDMapWidget"> + <p class="WidgetHeader NoBottomSpacing"> + <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="/map/default.aspx?lat=52.373217&lng=9.7108" target="_blank">View Larger Map</a> + </p> + + <div id="map_canvas" style="width: 325px; height: 325px;"> + </div> + <p class="WidgetFooter"> + <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a> + </p> + </div> + <div style="display: none;"> + <div id="mapPrintingNotes"> + To print the map in Firefox and Opera, enable background images in the print dialog. + <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()"> + Close + </a> + </div> + </div> -</div>
-
- <p class="NoPrint">
- <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span>
- <br />
- <span id="ctl00_ContentBody_FindText"></span>
- </p>
- <ul class="NoPrint">
- <li>
- ...other caches <a href="/seek/nearest.aspx?u=daniel354">hidden</a> or <a href="/seek/nearest.aspx?ul=daniel354">found</a> by this user
- </li>
-
- <li>
- ...nearby <a href="/seek/nearest.aspx?tx=32bc9333-5e52-4957-b0f6-5a2c8fc7b257&lat=52.373217&lng=9.710800">caches of this type</a>, <a href="/seek/nearest.aspx?tx=32bc9333-5e52-4957-b0f6-5a2c8fc7b257&lat=52.373217&lng=9.710800&f=1">that I haven't found</a>
- </li>
- <li>
- ...all nearby <a href="/seek/nearest.aspx?lat=52.373217&lng=9.710800">caches</a>, <a href="/seek/nearest.aspx?lat=52.373217&lng=9.710800&f=1">that I haven't found</a>
- </li>
- <li>
- ...all nearby <a href="http://www.waymarking.com/directory.aspx?f=1&lat=52.373217&lon=9.710800">waymarks on Waymarking.com</a>
- </li>
-
-
- </ul>
- <p class="NoPrint">
- <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span>
- </p>
- <span class="NoPrint">
-
-<ul>
- <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=52.37322&lng=9.7108" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+52%c2%b0+22.393+E+009%c2%b0+42.648+(GC1ZXX2)+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=52.37322&longitude=9.7108&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=52.37322&lon=9.7108&zoom=16&q=52.37322,9.7108&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.52.37322_9.7108_GC1ZXX2" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=52.37322&lon=9.7108" target="_blank">OpenCycleMap</a></li><li><a href="http://www.openstreetmap.org/?mlat=52.37322&mlon=9.7108&zoom=12" target="_blank">OpenStreetMap</a></li></span>
-</ul>
+</div> + + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span> + <br /> + <span id="ctl00_ContentBody_FindText"></span> + </p> + <ul class="NoPrint"> + <li> + ...other caches <a href="/seek/nearest.aspx?u=daniel354">hidden</a> or <a href="/seek/nearest.aspx?ul=daniel354">found</a> by this user + </li> + + <li> + ...nearby <a href="/seek/nearest.aspx?tx=32bc9333-5e52-4957-b0f6-5a2c8fc7b257&lat=52.373217&lng=9.710800">caches of this type</a>, <a href="/seek/nearest.aspx?tx=32bc9333-5e52-4957-b0f6-5a2c8fc7b257&lat=52.373217&lng=9.710800&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a href="/seek/nearest.aspx?lat=52.373217&lng=9.710800">caches</a>, <a href="/seek/nearest.aspx?lat=52.373217&lng=9.710800&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a href="http://www.waymarking.com/directory.aspx?f=1&lat=52.373217&lon=9.710800">waymarks on Waymarking.com</a> + </li> + + + </ul> + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span> + </p> + <span class="NoPrint"> + +<ul> + <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=52.37322&lng=9.7108" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+52%c2%b0+22.393+E+009%c2%b0+42.648+(GC1ZXX2)+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=52.37322&longitude=9.7108&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=52.37322&lon=9.7108&zoom=16&q=52.37322,9.7108&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.52.37322_9.7108_GC1ZXX2" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=52.37322&lon=9.7108" target="_blank">OpenCycleMap</a></li><li><a href="http://www.openstreetmap.org/?mlat=52.37322&mlon=9.7108&zoom=12" target="_blank">OpenStreetMap</a></li></span> +</ul> + + </span> + <ul class="CachePageImages NoPrint"> + + </ul> + + <div class="InformationWidget Clear"> + <h3> + 401 Logged Visits + </h3> + <div class="EncryptDecrypt"> + <a href="#" class="decrypt-link"> + Decrypt + </a> + </div> + <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 369 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 7 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 10 <img src="/images/logtypes/5.png" alt="Archive" title="Archive" /> 1 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 3 <img src="/images/logtypes/23.png" alt="Enable Listing" title="Enable Listing" /> 2 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 7 <img src="/images/logtypes/68.png" alt="Post Reviewer Note" title="Post Reviewer Note" /> 1 </p></span> + <p class="HalfLeft"> + <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View Logbook</a> | <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View the Image Gallery of 2 images</a> + </p> + <p class="NoBottomSpacing AlignRight"> + <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links. + </p> + </div> + + <div id="cache_logs_container"> + <table id="cache_logs_table" class="LogsTable NoBottomSpacing"> + <tbody> + </tbody> + <tfoot> + <tr> + <td class="AlignCenter"> + <div id="pnlLazyLoad" style="display: none;"> + <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" /> + Loading Cache Logs... + </div> + <div id="pnlButtonLoad" style="display: none;"> + <a class="MobileButton"> + Load More Logs...</a> + </div> + </td> + </tr> + </tfoot> + </table> + </div> + <p> + <small> + Current Time: <time datetime="2015-03-31T10:39:40Z">03/31/2015 10:39:40 Pacific Daylight Time (17:39 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2014-08-28T16:49:38Z">2014-08-28T16:49:38Z</time> on 08/28/2014 09:49:38 Pacific Daylight Time (16:49 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum + </small> + </p> + <div id="topScroll" class="TopScroll" style="display: none;"> + <a href="#Top"> </a> </div></div><script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl"> + <tr class="log-row" data-encoded="${IsEncoded}"> + <td> + <div class="FloatLeft LogDisplayLeft"> + <p class="logOwnerProfileName"> + <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong> + </p> + <p class="logOwnerBadge"> + <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle} + </p> + <p class="logOwnerAvatar"> + <a href="/profile/?guid=${AccountGuid}">{{if includeAvatars && AvatarImage}} + <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}"> + {{else includeAvatars }} + <img width="48" height="48" src="/images/default_avatar.jpg"> + {{/if}} + </a> + </p> + <p class="logOwnerStats"> + {{if GeocacheFindCount > 0 }} + <img title="Caches Found" src="/images/icons/16/found.png">${GeocacheFindCount} + {{/if}} + </p> + </div> + <div class="FloatLeft LogDisplayRight"> + <div class="HalfLeft LogType"> + <strong> + <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong> + </div> + <div class="HalfRight AlignRight"> + <span class="minorDetails LogDate">${Visited}</span> + </div> + <div class="Clear LogContent"> + {{if LatLonString.length > 0}} + <strong>${LatLonString}</strong> + {{/if}} + <p class="LogText">{{html LogText}}</p> + {{if Images.length > 0}} + <table cellspacing="0" cellpadding="3" class="LogImagesTable"> + {{tmpl(Images) "tmplCacheLogImages"}} + </table> + {{/if}} + + <div class="AlignRight"> + <small><a title="View Log" href="/seek/log.aspx?LUID=${LogGuid}" target="_blank">{{if (userInfo.ID==AccountID)}} + View / Edit Log / Images + {{else}} + View Log + {{/if}} + </a></small> + {{if (userInfo.ID==AccountID)}} + <small><a title="Upload Image" href="/seek/upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small> + {{/if}} + </div> + </div> + </div> + </td> + </tr> + </script><script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl"> + <tr> + <td> + + <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}"> + <img title="Photo" alt="Photo" src="/images/icons/16/photo.png"> + <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span> + </a> + </td> + </tr> + </script><script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl"> + <span class="LogImgTitle"> ${ $('<div /> + ').text($('<div /> + ').text($('<div /> + ').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink"> + + <a target="_blank" href="/seek/log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a> + + <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span> + + {{if (Descr && Descr.length > 0) }} + <br /><p class="LogImgDescription">${ $('<div /> + ').text($('<div /> + ').text($('<div /> + ').html($item.data.Descr).text()).html()).html() }</p> + {{/if}} + </script><script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl"> + <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}"> + <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4> + <dl> + <dt>Original:</dt> + <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd> + </dl> + <dl class="ccu-parse"> + <dt>Change To:</dt> + <dd> + <input type="text" max="40" size="35" class="cc-parse-text"> + <button class="ccu-button ccu-parse">Submit</button> + </dd> + </dl> + <dl class="ccu-parseverify" style="display: none;"> + <dt>Change To:</dt> + <dd> + <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span> + </dd> + <dt> </dt> + <dd> + <button class="ccu-button ccu-parseverify-accept">Accept</button> + <button class="ccu-button ccu-parseverify-cancel">Cancel</button> + </dd> + </dl> + </div> + </script> - </span>
- <ul class="CachePageImages NoPrint">
-
- </ul>
-
- <div class="InformationWidget Clear">
- <h3>
- 400 Logged Visits
- </h3>
- <div class="EncryptDecrypt">
- <a href="#" class="decrypt-link">
- Decrypt
- </a>
- </div>
- <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 368 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 7 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 10 <img src="/images/logtypes/5.png" alt="Archive" title="Archive" /> 1 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 3 <img src="/images/logtypes/23.png" alt="Enable Listing" title="Enable Listing" /> 2 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 7 <img src="/images/logtypes/68.png" alt="Post Reviewer Note" title="Post Reviewer Note" /> 1 </p></span>
- <p class="HalfLeft">
- <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View Logbook</a>Â |Â <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=36d45871-b99d-46d6-95fc-ff86ab564c98">View the Image Gallery of 2 images</a>
- </p>
- <p class="NoBottomSpacing AlignRight">
- <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links.
- </p>
- </div>
-
- <div id="cache_logs_container">
- <table id="cache_logs_table" class="LogsTable NoBottomSpacing">
- <tbody>
- </tbody>
- <tfoot>
- <tr>
- <td class="AlignCenter">
- <div id="pnlLazyLoad" style="display: none;">
- <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" />
- Loading Cache Logs...
- </div>
- <div id="pnlButtonLoad" style="display: none;">
- <a class="MobileButton">
- Load More Logs...</a>
- </div>
- </td>
- </tr>
- </tfoot>
- </table>
- </div>
- <p>
- <small>
- Current Time: <time datetime="2013-08-21T21:09:57Z">08/21/2013 21:09:57 Pacific Daylight Time (04:09 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2013-04-23T11:44:29Z">2013-04-23T11:44:29Z</time> on 04/23/2013 04:44:29 Pacific Daylight Time (11:44 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum
- </small>
- </p>
- <div id="topScroll" class="TopScroll" style="display: none;">
- <a href="#Top"> </a> </div></div><script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl">
- <tr class="log-row" data-encoded="${IsEncoded}">
- <td>
- <div class="FloatLeft LogDisplayLeft">
- <p class="logOwnerProfileName">
- <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong>
- </p>
- <p class="logOwnerBadge">
- <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle}
- </p>
- <p class="logOwnerAvatar">
- <a href="/profile/?guid=${AccountGuid}">{{if includeAvatars && AvatarImage}}
- <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}">
- {{else includeAvatars }}
- <img width="48" height="48" src="/images/default_avatar.jpg">
- {{/if}}
- </a>
- </p>
- <p class="logOwnerStats">
- {{if GeocacheFindCount > 0 }}
- <img title="Caches Found" src="/images/icons/16/found.png">${GeocacheFindCount}
- {{/if}}
- </p>
</div>
- <div class="FloatLeft LogDisplayRight">
- <div class="HalfLeft LogType">
- <strong>
- <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong>
- </div>
- <div class="HalfRight AlignRight">
- <span class="minorDetails LogDate">${Visited}</span>
- </div>
- <div class="Clear LogContent">
- {{if LatLonString.length > 0}}
- <strong>${LatLonString}</strong>
- {{/if}}
- <p class="LogText">{{html LogText}}</p>
- {{if Images.length > 0}}
- <table cellspacing="0" cellpadding="3" class="LogImagesTable">
- {{tmpl(Images) "tmplCacheLogImages"}}
- </table>
- {{/if}}
-
- <div class="AlignRight">
- <small><a title="View Log" href="/seek/log.aspx?LUID=${LogGuid}" target="_blank">{{if (userInfo.ID==AccountID)}}
- View / Edit Log / Images
- {{else}}
- View Log
- {{/if}}
- </a></small>
- {{if (userInfo.ID==AccountID)}}
- <small><a title="Upload Image" href="/seek/upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small>
- {{/if}}
- </div>
- </div>
- </div>
- </td>
- </tr>
- </script><script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl">
- <tr>
- <td>
-
- <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}">
- <img title="Photo" alt="Photo" src="/images/icons/16/photo.png">
- <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span>
- </a>
- </td>
- </tr>
- </script><script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl">
- <span class="LogImgTitle"> ${ $('<div />
- ').text($('<div />
- ').text($('<div />
- ').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink">
-
- <a target="_blank" href="/seek/log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a>
-
- <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span>
-
- {{if (Descr && Descr.length > 0) }}
- <br /><p class="LogImgDescription">${ $('<div />
- ').text($('<div />
- ').text($('<div />
- ').html($item.data.Descr).text()).html()).html() }</p>
- {{/if}}
- </script><script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl">
- <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}">
- <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4>
- <dl>
- <dt>Original:</dt>
- <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd>
- </dl>
- <dl class="ccu-parse">
- <dt>Change To:</dt>
- <dd>
- <input type="text" max="40" size="35" class="cc-parse-text">
- <button class="ccu-button ccu-parse">Submit</button>
- </dd>
- </dl>
- <dl class="ccu-parseverify" style="display: none;">
- <dt>Change To:</dt>
- <dd>
- <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span>
- </dd>
- <dt> </dt>
- <dd>
- <button class="ccu-button ccu-parseverify-accept">Accept</button>
- <button class="ccu-button ccu-parseverify-cancel">Cancel</button>
- </dd>
- </dl>
- </div>
- </script>
-
- </div>
-
- </div>
- </section>
- <footer>
- <div class="container">
- <div class="span-24 last FooterTop">
+ </div>
+ </section>
+ <footer>
+
+ <section class="links wrap">
+ <dl>
+ <dt>Partner With Us</dt>
+ <dd><a id="ctl00_hlFooterJobs" href="http://www.groundspeak.com/jobs.aspx">Jobs</a></dd>
+ <dd><a id="ctl00_lnkTravelAndGeotourism" href="/travel/">GeoTours & Travel</a></dd>
+ <dd><a id="ctl00_lnkBrandedPromotions" href="/brandedpromotions/">Branded Promotions</a></dd>
+ </dl>
-<div class="LocaleText">
-
- <strong>Choose Your Language:</strong>
-
-</div>
-<div class="LocaleList">
-
- <div class="selected-language">
-
- <a href="#">English▼</a>
-
- </div>
- <ul class="language-list">
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Latviešu</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, Bokmål</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li>
-
- </ul>
-
-</div>
-<script type="text/javascript">
+ <dl>
+ <dt>Legal</dt>
+ <dd><a id="ctl00_hlFooterLogo" accesskey="l" href="../about/logousage.aspx">Logo Usage Guidelines</a></dd>
+ <dd><a id="ctl00_hlFooterParksPoliceLink" href="../parksandpolice/">Parks & Police</a></dd>
+ </dl>
- jQuery(document).ready(function () {
- jQuery(".selected-language a").click(function (e) {
- e.preventDefault();
- var $loc = jQuery(this).parent().next();
- jQuery($loc).show().position({
- of: $loc.parent(),
- my: "left top",
- at: "left bottom",
- offset: "0 0",
- collision: "fit fit"
- });
- jQuery(this).addClass("Expanded");
- jQuery(document).click(function () {
- jQuery(".language-list").fadeOut("fast");
- jQuery(".selected-language a").removeClass("Expanded");
- });
- return false;
- });
- });
+ <dl>
+ <dt>Shop Geocaching</dt>
+ <dd><a id="ctl00_lnkUSAShop" href="http://shop.geocaching.com/">USA Shop</a></dd>
+ <dd><a id="ctl00_lnkInternationalShop" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></dd>
+ </dl>
+ <dl>
+ <dt>Contact Us</dt>
+ <dd><a id="ctl00_lnkHelpCenterLink" rel="external" href="http://support.groundspeak.com/index.php?pg=request">Help Center</a></dd>
+ <dd><a id="ctl00_lnkMedia" rel="document" href="../press/faq.aspx">Media Inquiries</a></dd>
+ </dl>
+ + +<div class="language-dropdown"> + <div class="LocaleText"> + Choose Language + </div> + <div class="LocaleList"> + + <div class="selected-language"> + + <a href="#">English</a> + + </div> + <ul class="language-list"> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" class="selected" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Català </a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">ÄŒeÅ¡tina</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Dansk</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Deutsch</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Ελληνικά</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Eesti</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Français</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">日本語</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">í•œêµì–´</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">LatvieÅ¡u</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Magyar</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Nederlands</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, BokmÃ¥l</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">Polski</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Português</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">РуÑÑкий</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl20_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl20$uxLocaleItem','')">Suomi</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl21_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl21$uxLocaleItem','')">Svenska</a></li> + + </ul> + + </div> +</div> +<script type="text/javascript"> + + jQuery(document).ready(function () { + jQuery(".selected-language a").click(function (e) { + e.preventDefault(); + var $loc = jQuery(this).parent().next(); + jQuery($loc).show().position({ + of: $loc.parent(), + my: "left bottom", + at: "left top-10", + collision: "fit fit" + }); + jQuery(this).addClass("Expanded"); + jQuery(document).click(function () { + jQuery(".language-list").fadeOut("fast"); + jQuery(".selected-language a").removeClass("Expanded"); + }); + return false; + }); + }); </script>
- </div>
- </div>
- <div class="container column-container">
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- About</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li>
- <li>
- <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li>
- <li>
- <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li>
- <li>
- <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Press</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li>
- <li>
- <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li>
- <li>
- <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li>
- <li>
- <a id="ctl00_hlFooterLogo" accesskey="l" title="Logo Usage Guidelines" href="../about/logousage.aspx">Logo Usage Guidelines</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Questions & Suggestions</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
- <li>
- <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
- <li>
- <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li>
- <li>
- <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Resources</strong>
+ </section>
+
+ <section class="copyright">
+ <div class="container">
+ <p>
+ © 2000-2015
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" href="../about/privacypolicy.aspx">Privacy Policy</a>
</p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li>
- <li>
- <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li>
- <li>
- <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Follow Us</strong>
- </p>
- <ul class="FooterLinks FollowUsLinks">
- <li>
- <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a></li>
- <li>
- <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a></li>
- <li>
- <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/gogeocaching/"></a></li>
- <li>
- <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a></li>
- </ul>
- </div>
- </div>
- <div class="FooterBottom">
- <div class="container">
- <p>
- Copyright
- © 2000-2013
- <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
- All Rights Reserved.
- <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
- |
- <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a>
- </p>
- </div>
+ <ul class="links-social">
+ <li>
+ <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/geocaching/"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a>
+ </li>
+ </ul>
+ </div>
+ </section>
+ </footer>
+ <div class="SkipLinks">
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
</div>
- </footer>
- <div class="SkipLinks">
- <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
- </div>
<script type="text/javascript">
//<![CDATA[
$(function() { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'Premium', null, true]); });var isLoggedIn = true;
-var userDefinedCoords = {"status":"fail","data":{"isUserDefined":false,"oldLatLngDisplay":"N 52° 22.393' E 009° 42.648'"}};
mapLatLng = {"lat":52.37322,"lng":9.7108,"type":2,"name":"Hannopoly: Eislisenstrasse "};
var ccConversions = [{"t":"Decimal","k":"DD","d":"WGS84","v":"52.373217, 009.710800"},{"t":"DDD MM SS.SSS","k":"DMS","d":"WGS84","v":"N 52° 22' 23.581\" E 009° 42' 38.880\""},{"t":"UTM","k":"UTM","d":"WGS84","v":"32U E 548389 N 5802787"}];
-var dh=true;userInfo = {ID: 4793174};
-userToken = '4OB3GFHLRR3CGMZFUAPD6CWPE24ZHP6Q7KCBEDNYY5CUNWNQIA32GZPVPFMH6IGAEYKVNNSFLMQ7BBGFDKQBT3BZGZBYKVQ4H5BWKD6MVBKYBTM627XPOUSUP6U4JF7NKKEOYJ4A6LEG2T5B6MG5AMMFOS27KNE4U2BAU4NSVGNBXHR5C6PR3SY43LQLEMQAK6P6L3C22DSDAIID4NQ45XT2T3KG4FTXH4IIKNQYTTQKBGW2EPKA';
-includeAvatars = true;
+var dh=true;userInfo = {ID: 3409138};
+userToken = 'ID5R2NBJDBPQYVKRP2QCKFMGOD72N345U34TRF3HIUOES7I3DEYZLGMWQENANSEL75TH743VWQXA4PRVBZVB2UFIVLT5HYFG73BJY737PC6AVOROLQCJBHWZ5WOPA4ZCUMZSO7RLBORYFW5XH4FZERAO4GV6P6EU7MMIJWUK6Y6H6ZYBXOJQGV2TV37BJNCBDOZM424FHCXLMVNTML7DPYTFQNNYH4Y45UUKWJTBTU3AJ5JVS7UA';
+includeAvatars = false;
var lat=52.373217, lng=9.7108, guid='36d45871-b99d-46d6-95fc-ff86ab564c98';
-initalLogs = {"status":"success", "data": [{"LogID":196904781,"CacheID":1433909,"LogGuid":"26f89faf-aa71-406e-9ea3-cdfa18a846e6","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"s. mein Log bei Seestr.","Created":"2011-11-05","Visited":"2011-11-05","UserName":"daniel354","MembershipLevel":3,"AccountID":1477880,"AccountGuid":"8186d342-6f46-4d9e-8ba3-2e7b51426798","Email":"","AvatarImage":"b82a4dec-bd35-4cc8-b6dc-fe8bced5cbca.jpg","GeocacheFindCount":5306,"GeocacheHideCount":43,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":196899232,"CacheID":1433909,"LogGuid":"f755b34d-0cc1-4740-827a-07311fe1a3b1","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"Äh, Logbuch ist nicht mehr vor Ort - wie kann man da \"Found\" loggen ? Ansonsten würde ich auch \"Found\" loggen da ich Dienstag vor Ort war und genau weiß vor sich der Cache befand....","Created":"2011-11-05","Visited":"2011-11-05","UserName":"blafoo","MembershipLevel":3,"AccountID":1912314,"AccountGuid":"0564a940-8311-40ee-8e76-7e91b2cf6284","Email":"","AvatarImage":"50f83123-27d8-4dcf-9fde-2af006efaf2b.jpg","GeocacheFindCount":829,"GeocacheHideCount":8,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":189731769,"CacheID":1433909,"LogGuid":"e674d2ed-7cac-4b49-96b1-3020e5c7f479","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Archive","LogTypeImage":"5.png","LogText":"Auch hier fehlt mir leider eine passende neue Idee. Wie alle archivierten Hannopolys wird auch diese Besitzrechtskarte ab sofort auf www.hannopoly.de zu finden sein. Danke für die sehr schönen Logs!","Created":"2011-10-01","Visited":"2011-10-01","UserName":"daniel354","MembershipLevel":3,"AccountID":1477880,"AccountGuid":"8186d342-6f46-4d9e-8ba3-2e7b51426798","Email":"","AvatarImage":"b82a4dec-bd35-4cc8-b6dc-fe8bced5cbca.jpg","GeocacheFindCount":5306,"GeocacheHideCount":43,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":189390319,"CacheID":1433909,"LogGuid":"4510051e-2c87-4d09-b77d-d90f645bafe9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"wahrscheinlich nicht mehr so schön wie geplant, dennoch alles da, was der logger so braucht ... sogar´n herry ;-)<br /><br />dfdc","Created":"2011-09-29","Visited":"2011-09-29","UserName":"Sir5al","MembershipLevel":3,"AccountID":3229535,"AccountGuid":"66de7735-1888-479b-8dbd-ada710747374","Email":"","AvatarImage":"9da1d6ed-3a3f-47cb-aba3-f5550abe7d11.jpg","GeocacheFindCount":1244,"GeocacheHideCount":6,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":186118551,"CacheID":1433909,"LogGuid":"acce0114-1712-4f32-b120-4b8bd4ef7200","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Leider habe ich erst gesehen das der Cache auf Eis liegt nach dem ich ihn gefunden habe.<br /><br />Ich konnte ihn denn noch gut finden und mich im großem Logbuch eintragen!<br /><br /><br />DFDC","Created":"2011-09-11","Visited":"2011-08-27","UserName":"Smootje1","MembershipLevel":3,"AccountID":4186572,"AccountGuid":"41b96bb9-ed81-473a-9032-1096d5c94423","Email":"","AvatarImage":"6052e05a-f2ce-45f1-86c4-c56fe8da6d2b.jpg","GeocacheFindCount":5132,"GeocacheHideCount":39,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":171398380,"CacheID":1433909,"LogGuid":"845e6ead-bf44-4dd8-900e-81a78afc0887","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"Daniel, du sprichst uns aus der Seele.. gestern Nacht dagewesen, um ihn ENDLICH zu heben, aber ohne Erfolg.. SCHNIEF","Created":"2011-07-08","Visited":"2011-07-08","UserName":"Steinbreit","MembershipLevel":3,"AccountID":4430835,"AccountGuid":"86281f53-49a2-4051-bc15-394d43724d65","Email":"","AvatarImage":"90f468a9-7059-43a7-a3c5-256879458a63.jpg","GeocacheFindCount":526,"GeocacheHideCount":8,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":171063566,"CacheID":1433909,"LogGuid":"fc463b7b-ce41-4d16-a7a4-2107b8454a91","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Temporarily Disable Listing","LogTypeImage":"22.png","LogText":"Mist...","Created":"2011-07-06","Visited":"2011-07-06","UserName":"daniel354","MembershipLevel":3,"AccountID":1477880,"AccountGuid":"8186d342-6f46-4d9e-8ba3-2e7b51426798","Email":"","AvatarImage":"b82a4dec-bd35-4cc8-b6dc-fe8bced5cbca.jpg","GeocacheFindCount":5306,"GeocacheHideCount":43,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":170116614,"CacheID":1433909,"LogGuid":"09c89c9c-ec9f-4387-a6ae-05fe6d11d9bf","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Ging schneller als gedacht. :-)<br /><br />TFTC","Created":"2011-07-02","Visited":"2011-07-01","UserName":"urbannature","MembershipLevel":1,"AccountID":2510965,"AccountGuid":"1f223c0d-d9ee-44c4-b411-35eee724b868","Email":"","AvatarImage":"476ea58f-a917-46c4-8e5a-b99484b514f6.jpg","GeocacheFindCount":2296,"GeocacheHideCount":10,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":168683009,"CacheID":1433909,"LogGuid":"53e3436d-3bbc-4b46-aa34-ca28bbd0723a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Erster Hanopoly-Cach! Nach langem suchen und richtig lesen gefunden! ;)","Created":"2011-06-24","Visited":"2011-06-24","UserName":"anady","MembershipLevel":1,"AccountID":3551788,"AccountGuid":"c6d0f76b-df41-44d0-9d1f-e60b0ffa4f0a","Email":"","AvatarImage":"","GeocacheFindCount":148,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":168640932,"CacheID":1433909,"LogGuid":"fc364b9d-8ddb-4d0e-aa42-09b4dce93c94","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zusammen mit anady hier gewesen und die bald Karte gefunden. Doch irgendwie war kein Logbuch auffindbar. Während wir noch etwas hin und her hantierten wurde es uns überraschend übergeben. Ob das so sein soll?<br /><br />Die Idee aber ist prima.<br /><br />TFTC! :-)","Created":"2011-06-24","Visited":"2011-06-24","UserName":"CriDi","MembershipLevel":3,"AccountID":3383487,"AccountGuid":"78aeaa8b-044d-40ac-8a80-656a1c7f85c1","Email":"","AvatarImage":"09f0aca7-6fcf-4d9a-bbf9-0f4b31c68f36.jpg","GeocacheFindCount":1594,"GeocacheHideCount":19,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":167383966,"CacheID":1433909,"LogGuid":"6a4c21a6-c795-4d8e-8f0c-a4d7a357f837","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Interessantes Geschehen am Sonnabendvormittag; die Müllabfuhr kommt, die Post bringt Neuigkeiten ins Haus, Nachbarn treffen sich auf der Straße und klönen eine Runde, ein Auto aus SFA blockiert die Kreuzung, ein Radfahrer entsorgt den Müll aus dem Fahrradkorb direkt am Baum und unser Team vergisst fast die Suche ...<br /><br />DfdC!","Created":"2011-06-18","Visited":"2011-06-18","UserName":"2bupa","MembershipLevel":3,"AccountID":2675170,"AccountGuid":"e6a84779-ad63-4ba1-93fa-558a7190c8b4","Email":"","AvatarImage":"e30c21ec-8bce-4b90-9c6f-ee7e618da9fe.jpg","GeocacheFindCount":6269,"GeocacheHideCount":14,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":167163052,"CacheID":1433909,"LogGuid":"2d51d81f-1581-4ae6-9254-0a5ffa163585","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"War schon öfters hier, aber die Muggels saßen da nur so rum. Heute früh aufgestanden....<br /><br />DFDC grüße Putze","Created":"2011-06-16","Visited":"2011-06-15","UserName":"Weltallputze","MembershipLevel":1,"AccountID":4512106,"AccountGuid":"07449e94-85c8-4d2f-b387-cb0910b2d854","Email":"","AvatarImage":"0b9746f6-1fd4-47b9-8f07-5b2bb3b21cc0.jpg","GeocacheFindCount":226,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":166633564,"CacheID":1433909,"LogGuid":"f6c8b6f6-527b-4ea0-ba85-8637cf47bd73","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Voll geil. Juhu und danke","Created":"2011-06-13","Visited":"2011-06-13","UserName":"Lumisch","MembershipLevel":1,"AccountID":4464524,"AccountGuid":"fcc7da31-928a-418f-ae3e-9f015b41ead6","Email":"","AvatarImage":"","GeocacheFindCount":54,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":165707570,"CacheID":1433909,"LogGuid":"1adb0f76-9bfa-47a4-a7f2-4b3aab0ffcfb","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"lecker eis :)","Created":"2011-06-09","Visited":"2011-06-09","UserName":"Nico Rohrssen","MembershipLevel":1,"AccountID":4523346,"AccountGuid":"3c66a437-1bbc-4cb1-bda0-8f609ac6efef","Email":"","AvatarImage":"","GeocacheFindCount":25,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":164530395,"CacheID":1433909,"LogGuid":"477f0186-9c2a-40f9-8696-98afb9868205","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nach langer sorgfältiger Vorplanung (an welchem Tag lohnt sich das frühe Aufstehen?) bei Sonnenaufgang angeschlichen und... gefunden! Gotcha! DfdC!","Created":"2011-06-03","Visited":"2011-06-03","UserName":"Deistermonster","MembershipLevel":3,"AccountID":4165483,"AccountGuid":"116149cb-3e0f-4c50-b51e-95b756d64da4","Email":"","AvatarImage":"54fe057c-f79a-4d82-b587-53c5b2b9386f.jpg","GeocacheFindCount":2046,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":164413372,"CacheID":1433909,"LogGuid":"e2c9bdad-9282-49f2-aba4-7e2ac058afa5","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Morgens um 6 Uhr muggelfrei geloggt.<img src=\"/images/icons/icon_smile_big.gif\" border=\"0\" align=\"middle\" />Endlich! Der war schon ewig geplant, aber um unserer Idee nachzugehen, fehlte zur \"normalen\" Tageszeit der Mut. Ist schon ein lustiges Versteck... TFTC sagt Soukousa","Created":"2011-06-03","Visited":"2011-06-03","UserName":"Soukousa","MembershipLevel":3,"AccountID":4154048,"AccountGuid":"399bef0c-1cdd-4024-a00e-3199484131af","Email":"","AvatarImage":"8480d5e4-f43e-48e5-a449-c01ce424ff05.jpg","GeocacheFindCount":2053,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":163515249,"CacheID":1433909,"LogGuid":"cda47e99-cd5f-4fc1-aa40-cb3bccff4f46","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Bei einem leckerem Eis das Logbuch siegniert.<br /><br />TFTC<br />Don Canallie","Created":"2011-05-29","Visited":"2011-05-29","UserName":"Don Canallie","MembershipLevel":3,"AccountID":3891097,"AccountGuid":"80970931-2e97-4291-abfd-564635f5d86f","Email":"","AvatarImage":"e6944e25-df18-45fb-acca-93ee08e923da.jpg","GeocacheFindCount":916,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":163307833,"CacheID":1433909,"LogGuid":"caad1abc-eb5c-4b99-ae92-232057825f41","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Während einer schönen Li-Li-Ahlem Fahrrad Cachingtour gesucht und geborgen, danach wieder korrekt versteckt, damit es nicht zu einfach wird. dfdc <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" />","Created":"2011-05-29","Visited":"2011-05-28","UserName":"rimini08","MembershipLevel":3,"AccountID":4088331,"AccountGuid":"2fe34526-d72d-478e-9b7f-9dc5c3e1d6c1","Email":"","AvatarImage":"","GeocacheFindCount":549,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":163325464,"CacheID":1433909,"LogGuid":"c3475f2f-1e55-43aa-89a8-3a1ce8ddc525","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"<i>gut gefunden, danke fürs verstecken!</i> <br /><br /><b> <font color=\"red\">TFTC<br /><br /><b> <font color=\"green\">...sprechenden Cachern kann geholfen werden <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /><br /><br /><img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /> <b> <font size=\"3\"> <font color=\"green\">J<font color=\"black\">o<font color=\"green\">h<font color=\"black\">a<font color=\"green\">n<font color=\"black\">s<font color=\"green\">i<font color=\"black\">b<font color=\"green\">ä<font color=\"black\">r <font color=\"orange\">2011</font> <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /></font></font></font></font></font></font></font></font></font></font></font></b><font size=\"3\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"></font></font></font></font></font></font></font></font></font></font></font></font></b></font></b>","Created":"2011-05-29","Visited":"2011-05-22","UserName":"Johansibär","MembershipLevel":3,"AccountID":1858674,"AccountGuid":"05f9d911-9cdc-4224-84b3-8e4923228958","Email":"","AvatarImage":"4d235c2f-81b6-42c4-a28c-5df2182a289d.jpg","GeocacheFindCount":1251,"GeocacheHideCount":17,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":162246062,"CacheID":1433909,"LogGuid":"e9eec580-6831-40ba-8530-c9722017a142","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schon vor ein paar Tagen die Karte entdeckt aber das loggen war uns nicht so klar...nun haben wir uns heute auch im Logbuch verewigt. Nette Idee, DfdC.","Created":"2011-05-22","Visited":"2011-05-22","UserName":"Flunin","MembershipLevel":1,"AccountID":3435189,"AccountGuid":"4c851b2a-967c-427d-91eb-268b5ffb0f0a","Email":"","AvatarImage":"","GeocacheFindCount":663,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161705502,"CacheID":1433909,"LogGuid":"0b303d23-fb26-4b29-b5d2-2bb8828682ae","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nach nem kleinen Tipp dann doch noch loggen können :-)<br />DFDC","Created":"2011-05-20","Visited":"2011-05-20","UserName":"Leafhoppers","MembershipLevel":1,"AccountID":3766111,"AccountGuid":"37bd64d5-a74f-4a12-b040-460f83652198","Email":"","AvatarImage":"","GeocacheFindCount":588,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161990811,"CacheID":1433909,"LogGuid":"1ac63b3e-075a-48b7-9a1f-222b19c71868","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zusammen mit i-teg um 15:25 Uhr geloggt. <br />TFTC!<br />#488","Created":"2011-05-21","Visited":"2011-05-19","UserName":"justify-jay","MembershipLevel":1,"AccountID":3936481,"AccountGuid":"af49ff9e-5331-4565-97e8-5f5bf45e33b2","Email":"","AvatarImage":"198d173a-7efa-416c-b495-b15ed30f94a1.jpg","GeocacheFindCount":1105,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161988577,"CacheID":1433909,"LogGuid":"19a1ae8a-e3d7-492c-a866-002064968183","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf Spontantour zusammen mit justify-jay um 15:25 Uhr zum Logbuch durchgedrungen :-) ! <br />TFTC!<br />#488","Created":"2011-05-21","Visited":"2011-05-19","UserName":"i-teg","MembershipLevel":1,"AccountID":3936536,"AccountGuid":"a30caa8b-0ba4-4a20-875f-ac825eacbf41","Email":"","AvatarImage":"533a43c0-8416-452f-8011-f575dee42268.jpg","GeocacheFindCount":1107,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161489085,"CacheID":1433909,"LogGuid":"0686f7dd-e12b-4b99-b7c7-24df895f48fb","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schnell gefunden da unsere Vorlogger scheinbar den Cache nicht wieder ganz genau plaziert hatten. Weils so schnell ging ne leckeres Eis in der Sonne genossen.<br />Ein super Cache, vielen Dank dafür.<br />Kartoffelhunter","Created":"2011-05-18","Visited":"2011-05-18","UserName":"Kartoffelhunter","MembershipLevel":1,"AccountID":3579558,"AccountGuid":"344121a1-10f3-443a-9ff6-f90fc43ba8be","Email":"","AvatarImage":"61105259-e319-4793-9bc3-51aae0eb9e10.jpg","GeocacheFindCount":1027,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":160254911,"CacheID":1433909,"LogGuid":"f315eb63-43e2-48ad-a3b9-fc775dfc9e27","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Unsere erste gefundene Hannopoly-Karte, bei bestem Wetter. Und zur Belohnung ein Lecker Eis für Leona, Tomke und mich.","Created":"2011-05-11","Visited":"2011-05-11","UserName":"janko74","MembershipLevel":1,"AccountID":4460156,"AccountGuid":"bc9f2cab-dad8-465f-8b73-0d7d420e043c","Email":"","AvatarImage":"","GeocacheFindCount":4,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 400, "rows": 400 } };
-var gaToken = 'UA-2020240-1';//]]>
+initalLogs = {"status":"success", "data": [{"LogID":196904781,"CacheID":1433909,"LogGuid":"26f89faf-aa71-406e-9ea3-cdfa18a846e6","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"s. mein Log bei Seestr.","Created":"2011-11-05","Visited":"2011-11-05","UserName":"daniel354","MembershipLevel":3,"AccountID":1477880,"AccountGuid":"8186d342-6f46-4d9e-8ba3-2e7b51426798","Email":"","AvatarImage":"b82a4dec-bd35-4cc8-b6dc-fe8bced5cbca.jpg","GeocacheFindCount":5581,"GeocacheHideCount":35,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":196899232,"CacheID":1433909,"LogGuid":"f755b34d-0cc1-4740-827a-07311fe1a3b1","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"Äh, Logbuch ist nicht mehr vor Ort - wie kann man da \"Found\" loggen ? Ansonsten würde ich auch \"Found\" loggen da ich Dienstag vor Ort war und genau weiß vor sich der Cache befand....","Created":"2011-11-05","Visited":"2011-11-05","UserName":"blafoo","MembershipLevel":3,"AccountID":1912314,"AccountGuid":"0564a940-8311-40ee-8e76-7e91b2cf6284","Email":"","AvatarImage":"816ea7ab-8878-4e22-8097-ba18294ac8d9.png","GeocacheFindCount":1312,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":189731769,"CacheID":1433909,"LogGuid":"e674d2ed-7cac-4b49-96b1-3020e5c7f479","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Archive","LogTypeImage":"5.png","LogText":"Auch hier fehlt mir leider eine passende neue Idee. Wie alle archivierten Hannopolys wird auch diese Besitzrechtskarte ab sofort auf www.hannopoly.de zu finden sein. Danke für die sehr schönen Logs!","Created":"2011-10-01","Visited":"2011-10-01","UserName":"daniel354","MembershipLevel":3,"AccountID":1477880,"AccountGuid":"8186d342-6f46-4d9e-8ba3-2e7b51426798","Email":"","AvatarImage":"b82a4dec-bd35-4cc8-b6dc-fe8bced5cbca.jpg","GeocacheFindCount":5581,"GeocacheHideCount":35,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":189390319,"CacheID":1433909,"LogGuid":"4510051e-2c87-4d09-b77d-d90f645bafe9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"wahrscheinlich nicht mehr so schön wie geplant, dennoch alles da, was der logger so braucht ... sogar´n herry ;-)<br /><br />dfdc","Created":"2011-09-29","Visited":"2011-09-29","UserName":"Sir5al","MembershipLevel":3,"AccountID":3229535,"AccountGuid":"66de7735-1888-479b-8dbd-ada710747374","Email":"","AvatarImage":"9da1d6ed-3a3f-47cb-aba3-f5550abe7d11.jpg","GeocacheFindCount":2131,"GeocacheHideCount":10,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":186118551,"CacheID":1433909,"LogGuid":"acce0114-1712-4f32-b120-4b8bd4ef7200","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Leider habe ich erst gesehen das der Cache auf Eis liegt nach dem ich ihn gefunden habe.<br /><br />Ich konnte ihn denn noch gut finden und mich im großem Logbuch eintragen!<br /><br /><br />DFDC","Created":"2011-09-11","Visited":"2011-08-27","UserName":"Smootje1","MembershipLevel":3,"AccountID":4186572,"AccountGuid":"41b96bb9-ed81-473a-9032-1096d5c94423","Email":"","AvatarImage":"1371a3ed-3fec-45bb-8fce-6c11de80f522.jpg","GeocacheFindCount":6163,"GeocacheHideCount":48,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":171398380,"CacheID":1433909,"LogGuid":"845e6ead-bf44-4dd8-900e-81a78afc0887","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"Daniel, du sprichst uns aus der Seele.. gestern Nacht dagewesen, um ihn ENDLICH zu heben, aber ohne Erfolg.. SCHNIEF","Created":"2011-07-08","Visited":"2011-07-08","UserName":"Steinbreit","MembershipLevel":3,"AccountID":4430835,"AccountGuid":"86281f53-49a2-4051-bc15-394d43724d65","Email":"","AvatarImage":"90f468a9-7059-43a7-a3c5-256879458a63.jpg","GeocacheFindCount":558,"GeocacheHideCount":8,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":171063566,"CacheID":1433909,"LogGuid":"fc463b7b-ce41-4d16-a7a4-2107b8454a91","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Temporarily Disable Listing","LogTypeImage":"22.png","LogText":"Mist...","Created":"2011-07-06","Visited":"2011-07-06","UserName":"daniel354","MembershipLevel":3,"AccountID":1477880,"AccountGuid":"8186d342-6f46-4d9e-8ba3-2e7b51426798","Email":"","AvatarImage":"b82a4dec-bd35-4cc8-b6dc-fe8bced5cbca.jpg","GeocacheFindCount":5581,"GeocacheHideCount":35,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":170116614,"CacheID":1433909,"LogGuid":"09c89c9c-ec9f-4387-a6ae-05fe6d11d9bf","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Ging schneller als gedacht. :-)<br /><br />TFTC","Created":"2011-07-02","Visited":"2011-07-01","UserName":"urbannature","MembershipLevel":1,"AccountID":2510965,"AccountGuid":"1f223c0d-d9ee-44c4-b411-35eee724b868","Email":"","AvatarImage":"476ea58f-a917-46c4-8e5a-b99484b514f6.jpg","GeocacheFindCount":2480,"GeocacheHideCount":10,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":168683009,"CacheID":1433909,"LogGuid":"53e3436d-3bbc-4b46-aa34-ca28bbd0723a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Erster Hanopoly-Cach! Nach langem suchen und richtig lesen gefunden! ;)","Created":"2011-06-24","Visited":"2011-06-24","UserName":"anady","MembershipLevel":1,"AccountID":3551788,"AccountGuid":"c6d0f76b-df41-44d0-9d1f-e60b0ffa4f0a","Email":"","AvatarImage":"","GeocacheFindCount":155,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":168640932,"CacheID":1433909,"LogGuid":"fc364b9d-8ddb-4d0e-aa42-09b4dce93c94","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zusammen mit anady hier gewesen und die bald Karte gefunden. Doch irgendwie war kein Logbuch auffindbar. Während wir noch etwas hin und her hantierten wurde es uns überraschend übergeben. Ob das so sein soll?<br /><br />Die Idee aber ist prima.<br /><br />TFTC! :-)","Created":"2011-06-24","Visited":"2011-06-24","UserName":"CriDi","MembershipLevel":3,"AccountID":3383487,"AccountGuid":"78aeaa8b-044d-40ac-8a80-656a1c7f85c1","Email":"","AvatarImage":"09f0aca7-6fcf-4d9a-bbf9-0f4b31c68f36.jpg","GeocacheFindCount":2074,"GeocacheHideCount":19,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":167383966,"CacheID":1433909,"LogGuid":"6a4c21a6-c795-4d8e-8f0c-a4d7a357f837","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Interessantes Geschehen am Sonnabendvormittag; die Müllabfuhr kommt, die Post bringt Neuigkeiten ins Haus, Nachbarn treffen sich auf der Straße und klönen eine Runde, ein Auto aus SFA blockiert die Kreuzung, ein Radfahrer entsorgt den Müll aus dem Fahrradkorb direkt am Baum und unser Team vergisst fast die Suche ...<br /><br />DfdC!","Created":"2011-06-18","Visited":"2011-06-18","UserName":"2bupa","MembershipLevel":3,"AccountID":2675170,"AccountGuid":"e6a84779-ad63-4ba1-93fa-558a7190c8b4","Email":"","AvatarImage":"e30c21ec-8bce-4b90-9c6f-ee7e618da9fe.jpg","GeocacheFindCount":8744,"GeocacheHideCount":15,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":167163052,"CacheID":1433909,"LogGuid":"2d51d81f-1581-4ae6-9254-0a5ffa163585","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"War schon öfters hier, aber die Muggels saßen da nur so rum. Heute früh aufgestanden....<br /><br />DFDC grüße Putze","Created":"2011-06-16","Visited":"2011-06-15","UserName":"Weltallputze","MembershipLevel":1,"AccountID":4512106,"AccountGuid":"07449e94-85c8-4d2f-b387-cb0910b2d854","Email":"","AvatarImage":"0b9746f6-1fd4-47b9-8f07-5b2bb3b21cc0.jpg","GeocacheFindCount":227,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":166633564,"CacheID":1433909,"LogGuid":"f6c8b6f6-527b-4ea0-ba85-8637cf47bd73","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Voll geil. Juhu und danke","Created":"2011-06-13","Visited":"2011-06-13","UserName":"Lumisch","MembershipLevel":1,"AccountID":4464524,"AccountGuid":"fcc7da31-928a-418f-ae3e-9f015b41ead6","Email":"","AvatarImage":"","GeocacheFindCount":54,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":165707570,"CacheID":1433909,"LogGuid":"1adb0f76-9bfa-47a4-a7f2-4b3aab0ffcfb","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"lecker eis :)","Created":"2011-06-09","Visited":"2011-06-09","UserName":"Nico Rohrssen","MembershipLevel":1,"AccountID":4523346,"AccountGuid":"3c66a437-1bbc-4cb1-bda0-8f609ac6efef","Email":"","AvatarImage":"","GeocacheFindCount":25,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":164530395,"CacheID":1433909,"LogGuid":"477f0186-9c2a-40f9-8696-98afb9868205","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nach langer sorgfältiger Vorplanung (an welchem Tag lohnt sich das frühe Aufstehen?) bei Sonnenaufgang angeschlichen und... gefunden! Gotcha! DfdC!","Created":"2011-06-03","Visited":"2011-06-03","UserName":"Deistermonster","MembershipLevel":3,"AccountID":4165483,"AccountGuid":"116149cb-3e0f-4c50-b51e-95b756d64da4","Email":"","AvatarImage":"54fe057c-f79a-4d82-b587-53c5b2b9386f.jpg","GeocacheFindCount":3342,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":164413372,"CacheID":1433909,"LogGuid":"e2c9bdad-9282-49f2-aba4-7e2ac058afa5","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Morgens um 6 Uhr muggelfrei geloggt.<img src=\"/images/icons/icon_smile_big.gif\" border=\"0\" align=\"middle\" />Endlich! Der war schon ewig geplant, aber um unserer Idee nachzugehen, fehlte zur \"normalen\" Tageszeit der Mut. Ist schon ein lustiges Versteck... TFTC sagt Soukousa","Created":"2011-06-03","Visited":"2011-06-03","UserName":"Soukousa","MembershipLevel":3,"AccountID":4154048,"AccountGuid":"399bef0c-1cdd-4024-a00e-3199484131af","Email":"","AvatarImage":"8480d5e4-f43e-48e5-a449-c01ce424ff05.jpg","GeocacheFindCount":3347,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":163515249,"CacheID":1433909,"LogGuid":"cda47e99-cd5f-4fc1-aa40-cb3bccff4f46","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Bei einem leckerem Eis das Logbuch siegniert.<br /><br />TFTC<br />Don Canallie","Created":"2011-05-29","Visited":"2011-05-29","UserName":"Don Canallie","MembershipLevel":3,"AccountID":3891097,"AccountGuid":"80970931-2e97-4291-abfd-564635f5d86f","Email":"","AvatarImage":"e6944e25-df18-45fb-acca-93ee08e923da.jpg","GeocacheFindCount":1208,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":163307833,"CacheID":1433909,"LogGuid":"caad1abc-eb5c-4b99-ae92-232057825f41","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Während einer schönen Li-Li-Ahlem Fahrrad Cachingtour gesucht und geborgen, danach wieder korrekt versteckt, damit es nicht zu einfach wird. dfdc <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" />","Created":"2011-05-29","Visited":"2011-05-28","UserName":"rimini08","MembershipLevel":3,"AccountID":4088331,"AccountGuid":"2fe34526-d72d-478e-9b7f-9dc5c3e1d6c1","Email":"","AvatarImage":"","GeocacheFindCount":635,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":163325464,"CacheID":1433909,"LogGuid":"c3475f2f-1e55-43aa-89a8-3a1ce8ddc525","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"<i>gut gefunden, danke fürs verstecken!</i> <br /><br /><b> <font color=\"red\">TFTC<br /><br /><b> <font color=\"green\">...sprechenden Cachern kann geholfen werden <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /><br /><br /><img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /> <b> <font size=\"3\"> <font color=\"green\">J<font color=\"black\">o<font color=\"green\">h<font color=\"black\">a<font color=\"green\">n<font color=\"black\">s<font color=\"green\">i<font color=\"black\">b<font color=\"green\">ä<font color=\"black\">r <font color=\"orange\">2011</font> <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /></font></font></font></font></font></font></font></font></font></font></font></b><font size=\"3\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"><font color=\"green\"><font color=\"black\"></font></font></font></font></font></font></font></font></font></font></font></font></b></font></b>","Created":"2011-05-29","Visited":"2011-05-22","UserName":"Johansibär","MembershipLevel":1,"AccountID":1858674,"AccountGuid":"05f9d911-9cdc-4224-84b3-8e4923228958","Email":"","AvatarImage":"4d235c2f-81b6-42c4-a28c-5df2182a289d.jpg","GeocacheFindCount":1278,"GeocacheHideCount":17,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":162246062,"CacheID":1433909,"LogGuid":"e9eec580-6831-40ba-8530-c9722017a142","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schon vor ein paar Tagen die Karte entdeckt aber das loggen war uns nicht so klar...nun haben wir uns heute auch im Logbuch verewigt. Nette Idee, DfdC.","Created":"2011-05-22","Visited":"2011-05-22","UserName":"Flunin","MembershipLevel":1,"AccountID":3435189,"AccountGuid":"4c851b2a-967c-427d-91eb-268b5ffb0f0a","Email":"","AvatarImage":"","GeocacheFindCount":842,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161705502,"CacheID":1433909,"LogGuid":"0b303d23-fb26-4b29-b5d2-2bb8828682ae","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nach nem kleinen Tipp dann doch noch loggen können :-)<br />DFDC","Created":"2011-05-20","Visited":"2011-05-20","UserName":"Leafhoppers","MembershipLevel":1,"AccountID":3766111,"AccountGuid":"37bd64d5-a74f-4a12-b040-460f83652198","Email":"","AvatarImage":"","GeocacheFindCount":603,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161990811,"CacheID":1433909,"LogGuid":"1ac63b3e-075a-48b7-9a1f-222b19c71868","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zusammen mit i-teg um 15:25 Uhr geloggt. <br />TFTC!<br />#488","Created":"2011-05-21","Visited":"2011-05-19","UserName":"justify-jay","MembershipLevel":1,"AccountID":3936481,"AccountGuid":"af49ff9e-5331-4565-97e8-5f5bf45e33b2","Email":"","AvatarImage":"198d173a-7efa-416c-b495-b15ed30f94a1.jpg","GeocacheFindCount":1106,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161988577,"CacheID":1433909,"LogGuid":"19a1ae8a-e3d7-492c-a866-002064968183","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf Spontantour zusammen mit justify-jay um 15:25 Uhr zum Logbuch durchgedrungen :-) ! <br />TFTC!<br />#488","Created":"2011-05-21","Visited":"2011-05-19","UserName":"i-teg","MembershipLevel":1,"AccountID":3936536,"AccountGuid":"a30caa8b-0ba4-4a20-875f-ac825eacbf41","Email":"","AvatarImage":"533a43c0-8416-452f-8011-f575dee42268.jpg","GeocacheFindCount":1107,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":161489085,"CacheID":1433909,"LogGuid":"0686f7dd-e12b-4b99-b7c7-24df895f48fb","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schnell gefunden da unsere Vorlogger scheinbar den Cache nicht wieder ganz genau plaziert hatten. Weils so schnell ging ne leckeres Eis in der Sonne genossen.<br />Ein super Cache, vielen Dank dafür.<br />Kartoffelhunter","Created":"2011-05-18","Visited":"2011-05-18","UserName":"Kartoffelhunter","MembershipLevel":1,"AccountID":3579558,"AccountGuid":"344121a1-10f3-443a-9ff6-f90fc43ba8be","Email":"","AvatarImage":"61105259-e319-4793-9bc3-51aae0eb9e10.jpg","GeocacheFindCount":1027,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":160254911,"CacheID":1433909,"LogGuid":"f315eb63-43e2-48ad-a3b9-fc775dfc9e27","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Unsere erste gefundene Hannopoly-Karte, bei bestem Wetter. Und zur Belohnung ein Lecker Eis für Leona, Tomke und mich.","Created":"2011-05-11","Visited":"2011-05-11","UserName":"janko74","MembershipLevel":1,"AccountID":4460156,"AccountGuid":"bc9f2cab-dad8-465f-8b73-0d7d420e043c","Email":"","AvatarImage":"","GeocacheFindCount":4,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 401, "rows": 401 } };
+var gaToken = 'UA-2020240-1';ga('create', 'UA-2020240-35', 'geocaching.com'); ga('send', 'pageview');//]]>
</script>
</form>
- <script type="text/javascript">
+ <script src="/js/jquery_plugins/tinynav.min.js"></script>
+ <script src="/js/matchMedia.js"></script>
+ <script src="/account/scripts/custom/message-center-header-widget.js"></script>
+ <script>
+ $('#messagecenterheaderwidget').messageCenterHeaderWidget();
+
var browserType = {
IE: !!(window.attachEvent && !window.opera),
Opera: !!window.opera,
@@ -1248,18 +1097,57 @@ var gaToken = 'UA-2020240-1';//]]> MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};
+ // Modernizr only identifies browsers that support touch events; Windows Phone and webOS handle touch differently
+ var isMobile = (/(webOS|hpwOS|IEMobile)/).test(navigator.userAgent);
+
$(function () {
- // Make the menu system play nice with all browsers:
- $('ul.Menu li').hover(function () {
- $(this).addClass('hover');
- $('ul:first', this).css('visibility', 'visible');
- }, function () {
- $(this).removeClass('hover');
- $('ul:first', this).css('visibility', 'hidden');
+ var $topMenuLinks = $('.Menu > li');
+
+ $topMenuLinks.children('a').each(function () {
+ $(this).on('touchstart click', function (e) {
+ e.stopPropagation();
+
+ var $this = $(this),
+ $parent = $(this).parent();
+
+ $topMenuLinks.removeClass('hover');
+
+ if (!$parent.hasClass('hover') && $this.hasClass('Dropdown')) {
+ e.preventDefault();
+ $parent.addClass('hover');
+ }
+ });
});
- if (!isiOS()) {
- // Constructing a Twitter-esque Login:
- $(".SignInLink").click(function (e) {
+
+ var $userMenuBtn = $('.logged-in-user .li-user-toggle');
+
+ $userMenuBtn.on('touchstart click', function (e) {
+ e.stopPropagation();
+ $(this).next('ul').addClass('user-expanded');
+ });
+
+ $(document).on('click', function (e) {
+ if ($('.user-expanded').length && !$(e.target).parents().hasClass("user-expanded")) {
+ $('.user-expanded').removeClass("user-expanded");
+ }
+ if (!$(e.target).parents().hasClass("Menu")) {
+ $topMenuLinks.removeClass("hover");
+ }
+ });
+
+ if (isMobile || Modernizr.touch) {
+ // Convert language dropdown to native select
+ $("ul.language-list .selected").parent().addClass("selected");
+ $(".selected-language a, ul.language-list").hide();
+ $(".language-list").tinyNav({
+ active: 'selected'
+ });
+ }
+
+
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").on('click', function (e) {
+ if (window.matchMedia("(min-width: 1000px)").matches) {
e.preventDefault();
$("#SignInWidget").toggle();
$(".ProfileWidget").toggleClass("WidgetOpen");
@@ -1272,21 +1160,14 @@ var gaToken = 'UA-2020240-1';//]]> }
});
return false;
- });
- }
+ }
+ });
+
if (!("placeholder" in document.createElement("input"))) {
$("#SignInWidget label").removeClass("hideMe");
}
- $('.SignedInProfileLink').truncate({
- width: 120,
- after: '&hellip;',
- center: false,
- addclass: false,
- addtitle: false
- });
-
// Hide the warning message if the user closed it already
if ($.cookie('hide_warning') != null) {
$(".WarningMessage").hide();
@@ -1299,739 +1180,735 @@ var gaToken = 'UA-2020240-1';//]]> function isiOS() {
return (
- (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
- );
- }
- });
- </script>
-
- <script type="text/javascript">
- <!--
-
- function s2gps(guid) {
- var w = window.open('/seek/sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no');
- w.focus();
- }
-
- function s2phone(wpid) {
- window.location.href='/seek/sendtophone.aspx?gc=' + wpid;
- }
-
- function pl(lc) {
- document.location.href='/seek/cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n');
- }
-
- function setNotification(id) {
- //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'});
- //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'});
- }
-
- function cmo(id) {
- Cookie.set('sn', true);
- }
-
- function pp(img) {
- var w = window.open(img);
- w.focus();
- }
-
- var map, bounds;
- var canUpdateFavoriteStatus = true;
- var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false;
- var logInitialLoaded = false;
- var $tfoot = $("#cache_logs_table").find("tfoot");
- var currentPageIdx = 1, totalPages = 1, pageSize = 10;
- var isBusy = false;
-
- var locString = {
- decrypt: 'Decrypt',
- encrypt: 'Encrypt'
- };
-
- $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle");
- $("#tmpl_CacheLogImages").template("tmplCacheLogImages");
- $("#tmpl_CacheLogRow").template("tmplCacheLogRow");
-
- $(".EncryptDecrypt")
- .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} })
- .click(function (e) {
- e.preventDefault();
- $("tr.log-row").each(function (i, obj) {
- var $obj = $(obj);
- if ($obj.data("encoded") == true) {
- var lt = $obj.find("p.LogText");
- //var ltDecoded = $('<div />').html(lt.html()).text();
- lt.html(convertROTStringWithBrackets(lt.html()));
- }
- });
-
- decryptLogs = !decryptLogs;
-
- $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
-
- return false;
- });
-
- function appendNewLogs(obj) {
-
- totalPages = obj.pageInfo.totalPages;
-
- var $newBody = $(document.createElement("TBODY"));
-
- $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody);
-
- $newBody.find("a.tb_images").each(function()
- {
- var $this = $(this);
- $this.fancybox({
- 'type': 'image',
- 'titlePosition': 'inside',
- 'padding': 10,
- titleFormat: function() { return $this.data('title'); }
- });
- });
-
- $("#cache_logs_table")
- .append($newBody.children());
-
- currentPageIdx = obj.pageInfo.idx + 1;
- pageSize = obj.pageInfo.size;
- }
-
- var showScroll = false;
-
- function callLogLoad(hideFooter) {
- if (screen.width > 1090){
- showScroll = true;
- }
- $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs },
- function (response) {
- if (response.status == "success") {
- appendNewLogs(response);
- if( hideFooter || (totalPages < currentPageIdx) ) {
- $tfoot.hide();
- }
- } else if (response.status == "error" && response.value == "1") {
- // reload the page since the data had expired.
- window.location.reload();
- }
- isBusy = false;
- });
- }
-
- $("#add_to_favorites").click(function () {
-
- if (canUpdateFavoriteStatus) {
- canUpdateFavoriteStatus = false;
-
- var fv = parseInt($(".favorite-value").text());
- fv++;
- $(".favorite-value").text(fv);
-
- var fr = parseInt($(".favorite-rank").text());
- fr--;
- $(".favorite-rank").text(fr);
-
- $("#pnlNonfavoriteCache").fadeOut("fast", function () {
- $("#pnlFavoriteCache").fadeIn("fast");
- });
-
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true',
- success: function () {
- canUpdateFavoriteStatus = true;
- gotScore = false;
- showFavoriteScore();
- }
- });
-
- return false;
- }
- });
-
- $("#remove_from_favorites").click(function () {
-
- if (canUpdateFavoriteStatus) {
- canUpdateFavoriteStatus = false;
-
- var fv = parseInt($(".favorite-value").text());
- fv--;
- $(".favorite-value").text(fv);
-
- var fr = parseInt($(".favorite-rank").text());
- fr++;
- $(".favorite-rank").text(fr);
-
- $("#pnlFavoriteCache").fadeOut("fast", function () {
- $("#pnlNonfavoriteCache").fadeIn("fast");
- });
-
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false',
- success: function () {
- canUpdateFavoriteStatus = true;
- gotScore = false;
- showFavoriteScore();
- }
- });
-
- return false;
- }
- });
-
- $(function () {
-
- // CSP Section
- if ($("#cspMessage").length) {
-
- var editLink = $('a[href*="report.aspx"]').attr('href');
-
- $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>');
- $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>');
- $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>');
-
- $("#cspGoBack").click(function (e) {
- e.preventDefault();
- window.location = editLink;
- return false;
- });
-
- $("#cspSubmit").click(function (e) {
- e.preventDefault();
- $.pageMethod("/seek/cache_details.aspx/EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.success == true) {
- window.location = '/seek/cache_details.aspx?guid=' + r.guid;
- } else {
- alert("There was an error enabling your cache.");
- }
- });
- return false;
- });
-
- $("#cspConfirm").change(function() {
- if ($("#cspConfirm").is(":checked")) {
- $("#cspSubmit").removeAttr('disabled');
- $("#cspGoBack").attr('disabled', true);
- } else {
- $("#cspSubmit").attr('disabled', true);
- $("#cspGoBack").removeAttr('disabled');
- }
- });
- }
-
-
- //override coords
- if (typeof(userDefinedCoords) != "undefined") {
- if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) {
- mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
- $("#uxLatLon")
- .data("isOverridden", true)
- .addClass("myLatLon");
- } else if (userDefinedCoords.status == "success") {
- mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
- } else {
- $("#uxLatLonLink").contents().unwrap();
- }
- } else {
- $("#uxLatLonLink").contents().unwrap();
- }
-
-
- var cacheNoteText = {
- DefaultText: 'Click to enter a note',
- ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.',
- SavingText: 'Please wait, saving your note...'
- };
-
-
-
- $("time.timeago").timeago();
-
- $(".button").button();
-
- var sn = Cookie.get('sn');
-
- if ($('#trNotPM').length > 0) {
- $('#trNotPM').toggle(!sn);
- }
-
- $("#cache_note").editInPlace({
- callback: function (unused, enteredText) {
- var me = $(this);
-
- var et = $.trim(enteredText);
- if (et.length > 500 ) {
- et = et.substr(0, 500);
- }
- $.pageMethod("/seek/cache_details.aspx/SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) {
- var r = JSON.parse(r.d);
- if (r.success == true) {
- if ($.trim(r.note) == "") {
- $("#cache_note").text(cacheNoteText.DefaultText);
- } else {
- $("#cache_note").text(r.note);
- }
-
- me.effect('highlight', { color: '#ffb84c' }, 'slow');
- } else {
- alert(cacheNoteText.ErrorInSaving);
- $("#cache_note").text(cacheNoteText.DefaultText);
- }
-
- });
-
- return cacheNoteText.SavingText;
- }
- , default_text: cacheNoteText.DefaultText
- , field_type: "textarea"
- , textarea_rows: "7"
- , textarea_cols: "65"
- , show_buttons: true
- , bg_over: "#dad7cb"
- //, callback_skip_dom_reset: true
-
- });
-
- $("#lnk_slippyMap").click(function(e) {
- e.preventDefault();
- loadDynamicMap();
- return false;
- });
-
- $(".inplace_field").live("focus", function () {
- if ($(this).data("created") == null) {
- $(this).data("created", true)
- $(this).countable({
- maxLength: 500
- });
- }
- });
-
- $("#pcn_help").qtip({
- content: 'Enter your own notes here. No other user will be able to access them.',
- position: {
- my: 'top center',
- at: 'bottom center'
- },
- style: {
- classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip'
- },
- });
- $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
-
- if ($("#cache_logs_container").length > 0) {
-
- appendNewLogs(initalLogs);
-
- if (DetectMobileQuick()) {
- $("#pnlButtonLoad")
- .show()
- .find("a.MobileButton")
- .click(function (e) {
- e.preventDefault();
- callLogLoad(false);
- return false;
- })
- .button();
- if(!DetectTierTablet()){
- $("a.MobileButton").addClass("Phone");
- }
- } else {
- $("#pnlLazyLoad").show();
-
- $(window).endlessScroll({
- fireOnce: true,
- fireDelay: 500,
- bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50,
- ceaseFire: function(){
- // stop the scrolling if the last page is reached.
- return (isLoggedIn == false) || (totalPages < currentPageIdx);
- },
- callback: function() {
- if (!isBusy) {
-
- isBusy = true;
- $tfoot.show();
- callLogLoad(true);
- }
- }
- });
- }
- }
-
- if (!isLoggedIn) {
- $("#cache_logs_table").find("tfoot").hide();
- }
-
- if (mapLatLng != null) {
-
- $("#uxLatLonLink").qtip({
- suppress:false,
- content: buildCacheCoordMenu(),
- position: {
- my: 'left top',
- at: 'right top',
- adjust: {
- x: 10, y: -10
- }
- },
- show: {
- ready: false,
- event: "click",
- solo: true
- }, hide: {
- event: 'unfocus'
- },
- style: {
- tip: {
- corner: false
- },
- classes: 'ui-tooltip-widget'
- },
- events: {
- show: function () {
- if ($("#uxLatLon").data("isOverridden")) {
- $("a.ccu-restore").show();
- } else {
- $("a.ccu-restore").hide();
- }
-
- if (userDefinedCoords.status != "success") {
- $("div.ccu-update").hide();
- } else {
- $("div.ccu-update").show();
- }
- }
- }
- }).click(function (e) {
- e.preventDefault();
- return false;
- });
-
- setStaticMaps();
- //$("#staticMap").lazyload();
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
}
});
-
- function setStaticMaps() {
- var llBounds = new L.LatLngBounds();
-
- var map = new L.Map('map_preview_canvas', {
- center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- zoom: 10,
- doubleClickZoom: false,
- dragging: false,
- touchZoom: false,
- scrollWheelZoom: false,
- attributionControl: false
- })
- .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }));
-
- var mapLarge = new L.Map('map_canvas', {
- center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- zoom: 14,
- doubleClickZoom: true,
- dragging: true,
- touchZoom: false,
- scrollWheelZoom: false,
- zoomControl: true,
- attributionControl: false
- })
- .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }))
- .addControl(new L.Control.Scale());
-
- llBounds.extend(new L.LatLng(mapLatLng.lat, mapLatLng.lng));
-
- var tileOptions = {
- tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg",
- name: "mpqosm",
- alt: "MapQuest",
- //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ",
- subdomains: "1234",
- tileSize: 256,
- minZoom: 0,
- maxZoom: 18
- };
-
- map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
- mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
-
- var pinIcon = L.Icon.extend({
- iconSize: new L.Point(20, 23),
- iconAnchor: new L.Point(10,23),
- shadowUrl: null
- });
-
- var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
- title: mapLatLng.name
- })
- .on("click", function () {
- document.getElementById("uxlrgMap").scrollIntoView(true);
- return false;
- });
-
- var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
- clickable: false, zIndexOffset:99, title: mapLatLng.name
- });
-
- map.addLayer(mkA);
- mapLarge.addLayer(mkA2);
-
- $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({
- overlayShow: false
- });
-
- if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) {
-
- for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) {
-
- var item = cmapAdditionalWaypoints[x],
- ll = new L.LatLng(item.lat, item.lng),
- marker = new L.Marker(ll, {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}),
- title: item.name,
- clickable:false
- });
-
- llBounds.extend(ll);
- mapLarge.addLayer(marker);
- }
- var bz = mapLarge.getBoundsZoom(llBounds.pad(1.1));
-
- mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz);
- }
- }
-
- var lnkDH = $('#ctl00_ContentBody_lnkDH');
- function dht() {
- try {
- $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html()));
- var linkText = ((lnkDH.attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt');
- lnkDH
- .text(linkText)
- .attr('title', linkText);
- } catch (e) {
- alert(e);
- return false;
- }
- return false;
- }
-
- function buildCacheCoordMenu() {
- var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng)
- $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" );
-
- var $menu = $("<div></div>");
-
- $( "#tmpl_CacheCoordinateUpdate" ).tmpl( {
- ll: [mapLatLng.lat, mapLatLng.lng],
- ll_formatted: mapLatLng.oldLatLngDisplay
- } ).appendTo( $menu );
-
- $menu.find("button.ccu-button").button();
-
- $menu.delegate("button.ccu-parse", "click", function (e) {
- e.preventDefault();
- var $this = $(e.target),
- $parse =$this.closest('dd').find(".cc-parse-text"),
- parseCoords = $.trim($parse.val());
-
- if (parseCoords.length == 0) {
- alert('Please provide valid coordinates.');
- } else {
- $.getJSON("/api/geocode", { parse: parseCoords}, function (response) {
- if (response.status == "success") {
- var newLatLng = new LatLon(response.data.lat, response.data.lng);
-
- // update the displayed coords
- var dist = curLatLng.rhumbDistanceTo(newLatLng);
- var bearingTo = curLatLng.rhumbBearingTo(newLatLng);
- var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N";
-
- var formats = response.data.formats;
- // all these finds, make me feel dirty
- $menu
- .find("span.ccu-parseverify-coords").text(formats.DM).end()
- .find("dl.ccu-parse").hide().end()
- .find("dl.ccu-parseverify").show().end()
- .find("button.ccu-parseverify-accept")
- .data("utm", '')
- .data("dm", formats.DM)
- .data("lat", response.data.lat)
- .data("lng", response.data.lng)
- .end();
- } else {
- alert("Sorry unable to parse the coordinates you entered.");
- }
- });
- }
-
- return false;
- });
-
- $menu.delegate("button.ccu-parseverify-accept", "click", function (e) {
- e.preventDefault();
- var $this = $(this);
- // update to webmethod
- $.pageMethod("/seek/cache_details.aspx/SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.status == "success") {
- window.location.reload();
- } else {
- $("#uxLatLonLink").qtip('hide');
- }
-
- });
-
- return false;
- });
-
- $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) {
- e.preventDefault();
- $menu
- .find("input.cc-parse-text").val('').end()
- .find("dl.ccu-parse").show().end()
- .find("dl.ccu-parseverify").hide().end();
- return false;
- });
-
- $menu.delegate("a.ccu-restore", "click", function (e) {
- e.preventDefault();
-
- $.pageMethod("/seek/cache_details.aspx/ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.status == "success") {
- window.location.reload();
- }
- });
-
- return false;
- });
-
- return $menu;
- }
-
- GSPK = window.GSPK || {};
- GSPK.Selector = {};
- GSPK.Selector.getSelected = function(){
- var t = null;
- if ( window.getSelection ){
- t = window.getSelection();
- }else if(document.getSelection){
- t = document.getSelection();
- }else if(document.selection){
- t = document.selection.createRange().text;
- }
- return t;
- }
- //-->
</script>
- <script id="loc_favPointsScoreDesc" type="text/html">
- Favorites/Premium Logs
- </script>
- <script type="text/javascript" language="javascript">
- <!--
- var gotScore = false;
- var favDropDown = $('.favorite-dropdown');
- var favContainer = $('.favorite-container');
-
- function showFavoriteScore() {
- $('#imgFavoriteScore').attr('src', '/images/loading3.gif');
-
- $('#uxFavoriteScore').parent().fadeTo(200, .001, function () {
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/score?u=' + userToken,
- success: function (scoreResult) {
- gotScore = true;
-
- var score = 0;
-
- if(scoreResult)
- score = scoreResult;
-
- if(score > 100)
- score = 100;
-
- $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png');
- var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim();
- $('#imgFavoriteScore').attr('alt', pieDesc);
- $('#imgFavoriteScore').attr('title', pieDesc);
-
- $('#uxFavoriteScore').parent().fadeTo(1000, 1);
- $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html());
- }
- });
- });
- }
- var scrollId = false,
- logTop = $("#cache_logs_container").position().top;
- $(window).on("scroll", function() {
- if (scrollId != false) {
- window.clearTimeout(scrollId);
- scrollId = false;
- }
+ + <script type="text/javascript"> + <!-- + + function s2gps(guid) { + var w = window.open('/seek/sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no'); + w.focus(); + } + + function s2phone(wpid) { + window.location.href='/seek/sendtophone.aspx?gc=' + wpid; + } + + function pl(lc) { + document.location.href='/seek/cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n'); + } + + function setNotification(id) { + //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'}); + //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'}); + } + + function cmo(id) { + Cookie.set('sn', true); + } + + function pp(img) { + var w = window.open(img); + w.focus(); + } + + var map, bounds; + var canUpdateFavoriteStatus = true; + var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false; + var logInitialLoaded = false; + var $tfoot = $("#cache_logs_table").find("tfoot"); + var currentPageIdx = 1, totalPages = 1, pageSize = 10; + var isBusy = false; + + var locString = { + decrypt: 'Decrypt', + encrypt: 'Encrypt' + }; + + $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle"); + $("#tmpl_CacheLogImages").template("tmplCacheLogImages"); + $("#tmpl_CacheLogRow").template("tmplCacheLogRow"); + + $(".EncryptDecrypt") + .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} }) + .click(function (e) { + e.preventDefault(); + $("tr.log-row").each(function (i, obj) { + var $obj = $(obj); + if ($obj.data("encoded") == true) { + var lt = $obj.find("p.LogText"); + //var ltDecoded = $('<div />').html(lt.html()).text(); + lt.html(convertROTStringWithBrackets(lt.html())); + } + }); + + decryptLogs = !decryptLogs; + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + return false; + }); + + function appendNewLogs(obj) { + + totalPages = obj.pageInfo.totalPages; + + var $newBody = $(document.createElement("TBODY")); + + $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody); + + $newBody.find("a.tb_images").each(function() + { + var $this = $(this); + $this.fancybox({ + 'type': 'image', + 'titlePosition': 'inside', + 'padding': 10, + titleFormat: function() { return $this.data('title'); } + }); + }); + + $("#cache_logs_table") + .append($newBody.children()); + + currentPageIdx = obj.pageInfo.idx + 1; + pageSize = obj.pageInfo.size; + } + + var showScroll = false; + + function callLogLoad(hideFooter) { + if (screen.width > 1090){ + showScroll = true; + } + $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs }, + function (response) { + if (response.status == "success") { + appendNewLogs(response); + if( hideFooter || (totalPages < currentPageIdx) ) { + $tfoot.hide(); + } + } else if (response.status == "error" && response.value == "1") { + // reload the page since the data had expired. + window.location.reload(); + } + isBusy = false; + }); + } + + $("#add_to_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv++; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr--; + $(".favorite-rank").text(fr); + + $("#pnlNonfavoriteCache").fadeOut("fast", function () { + $("#pnlFavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $("#remove_from_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv--; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr++; + $(".favorite-rank").text(fr); + + $("#pnlFavoriteCache").fadeOut("fast", function () { + $("#pnlNonfavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $(function () { + + // CSP Section + if ($("#cspMessage").length) { + + var editLink = $('a[href*="report.aspx"]').attr('href'); + + $("#cspMessage").prepend('<P><strong>Already submitted this geocache?</strong> Please check below for the Reviewer’s notes and make any necessary changes before you resubmit. You can also respond by clicking "Log Your Visit" and posting a Reviewer Note.</P>'); + $("#cspMessage").prepend('<P>Your geocache has not been published. Once your geocache is in place and all of the details have been entered, click "Submit for Review". A volunteer reviewer will begin the review process within about 7 days.</P>'); + + $("#cspGoBack").click(function (e) { + e.preventDefault(); + window.location = editLink; + return false; + }); + + $("#cspSubmit").click(function (e) { + e.preventDefault(); + $.pageMethod("/seek/cache_details.aspx/EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + window.location = '/seek/cache_details.aspx?guid=' + r.guid; + } else { + alert("There was an error enabling your cache."); + } + }); + return false; + }); + + + } + + + //override coords + if (typeof(userDefinedCoords) != "undefined") { + if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + $("#uxLatLon") + .data("isOverridden", true) + .addClass("myLatLon"); + } else if (userDefinedCoords.status == "success") { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + } else { + $("#uxLatLonLink").contents().unwrap(); + } + } else { + $("#uxLatLonLink").contents().unwrap(); + } + + + var cacheNoteText = { + DefaultText: 'Click to enter a note', + ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.', + SavingText: 'Please wait, saving your note...' + }; + + + + $("time.timeago").timeago(); + + $(".button").button(); + + var sn = Cookie.get('sn'); + + if ($('#trNotPM').length > 0) { + $('#trNotPM').toggle(!sn); + } + + $("#cache_note").editInPlace({ + callback: function (unused, enteredText) { + var me = $(this); + + var et = $.trim(enteredText); + if (et.length > 500 ) { + et = et.substr(0, 500); + } + $.pageMethod("/seek/cache_details.aspx/SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + if ($.trim(r.note) == "") { + $("#cache_note").text(cacheNoteText.DefaultText); + } else { + $("#cache_note").text(r.note); + } + + me.effect('highlight', { color: '#ffb84c' }, 'slow'); + } else { + alert(cacheNoteText.ErrorInSaving); + $("#cache_note").text(cacheNoteText.DefaultText); + } + + }); + + return cacheNoteText.SavingText; + } + , default_text: cacheNoteText.DefaultText + , field_type: "textarea" + , textarea_rows: "7" + , textarea_cols: "65" + , show_buttons: true + , bg_over: "#dad7cb" + //, callback_skip_dom_reset: true + + }); + + $("#lnk_slippyMap").click(function(e) { + e.preventDefault(); + loadDynamicMap(); + return false; + }); + + $(".inplace_field").live("focus", function () { + if ($(this).data("created") == null) { + $(this).data("created", true) + $(this).countable({ + maxLength: 500 + }); + } + }); + + $("#pcn_help").qtip({ + content: 'Enter your own notes here. No other user will be able to access them.', + position: { + my: 'top center', + at: 'bottom center' + }, + style: { + classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip' + }, + }); + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + if ($("#cache_logs_container").length > 0) { + + appendNewLogs(initalLogs); + + if (DetectMobileQuick()) { + $("#pnlButtonLoad") + .show() + .find("a.MobileButton") + .click(function (e) { + e.preventDefault(); + callLogLoad(false); + return false; + }) + .button(); + if(!DetectTierTablet()){ + $("a.MobileButton").addClass("Phone"); + } + } else { + $("#pnlLazyLoad").show(); + + $(window).endlessScroll({ + fireOnce: true, + fireDelay: 500, + bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50, + ceaseFire: function(){ + // stop the scrolling if the last page is reached. + return (isLoggedIn == false) || (totalPages < currentPageIdx); + }, + callback: function() { + if (!isBusy) { + + isBusy = true; + $tfoot.show(); + callLogLoad(true); + } + } + }); + } + } + + if (!isLoggedIn) { + $("#cache_logs_table").find("tfoot").hide(); + } + + if (mapLatLng != null) { + + $("#uxLatLonLink").qtip({ + suppress:false, + content: buildCacheCoordMenu(), + position: { + my: 'left top', + at: 'right top', + adjust: { + x: 10, y: -10 + } + }, + show: { + ready: false, + event: "click", + solo: true + }, hide: { + event: 'unfocus' + }, + style: { + tip: { + corner: false + }, + classes: 'ui-tooltip-widget' + }, + events: { + show: function () { + if ($("#uxLatLon").data("isOverridden")) { + $("a.ccu-restore").show(); + } else { + $("a.ccu-restore").hide(); + } + + if (userDefinedCoords.status != "success") { + $("div.ccu-update").hide(); + } else { + $("div.ccu-update").show(); + } + } + } + }).click(function (e) { + e.preventDefault(); + return false; + }); + + $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({ + overlayShow: false + }); + + setStaticMaps(); + } + }); + + function setStaticMaps() { + + var map = new L.Map('map_preview_canvas', { + center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), + zoom: 10, + doubleClickZoom: false, + dragging: false, + touchZoom: false, + scrollWheelZoom: false, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })); + + var mapLarge = L.map('map_canvas', { + center: [mapLatLng.lat, mapLatLng.lng], + zoom: 14, + doubleClickZoom: true, + dragging: true, + touchZoom: false, + scrollWheelZoom: false, + zoomControl: true, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })) + .addControl(new L.Control.Scale()); + + var tileOptions = { + tileUrl: "https://otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg", + //name: "mpqosm", + //alt: "MapQuest", + subdomains: "1234", + //tileSize: 256, + minZoom: 0, + maxZoom: 18 + }; + + map.addLayer(L.tileLayer(tileOptions.tileUrl, tileOptions)); + + L.tileLayer(tileOptions.tileUrl, tileOptions) + .addTo(mapLarge); + + var pinIcon = L.Icon.extend({ + iconSize: new L.Point(20, 23), + iconAnchor: new L.Point(10,23), + shadowUrl: null + }); + + var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), + { + icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}), + title: mapLatLng.name + }) + .on("click", function () { + document.getElementById("uxlrgMap").scrollIntoView(true); + return false; + }); + + L.marker([mapLatLng.lat, mapLatLng.lng], { + icon: L.icon({iconUrl: '/images/wpttypes/pins/' + mapLatLng.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23]}), + clickable: false, + //zIndexOffset: 99, + title: mapLatLng.name + }).addTo(mapLarge); + + map.addLayer(mkA); + + if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) { + + var llBounds = L.latLngBounds([mapLatLng.lat, mapLatLng.lng], [mapLatLng.lat, mapLatLng.lng]); + + for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) { + + var item = cmapAdditionalWaypoints[x], + ll = [item.lat, item.lng]; + + L.marker(ll, { + icon: L.icon({ iconUrl: '/images/wpttypes/pins/'+ item.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23] }), + title: item.name, + clickable: false + }).addTo(mapLarge); + + llBounds.extend(ll); + } + + window.setTimeout(function () { + mapLarge.fitBounds(llBounds.pad(.5)); + }, 100); + + } + } + + var lnkDH = $('#ctl00_ContentBody_lnkDH'); + function dht() { + try { + $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html())); + var linkText = ((lnkDH.attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt'); + lnkDH + .text(linkText) + .attr('title', linkText); + } catch (e) { + alert(e); + return false; + } + return false; + } + + function buildCacheCoordMenu() { + var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng) + $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" ); + + var $menu = $("<div></div>"); + + $( "#tmpl_CacheCoordinateUpdate" ).tmpl( { + ll: [mapLatLng.lat, mapLatLng.lng], + ll_formatted: mapLatLng.oldLatLngDisplay + } ).appendTo( $menu ); + + $menu.find("button.ccu-button").button(); + + $menu.delegate("button.ccu-parse", "click", function (e) { + e.preventDefault(); + var $this = $(e.target), + $parse =$this.closest('dd').find(".cc-parse-text"), + parseCoords = $.trim($parse.val()); + + if (parseCoords.length == 0) { + alert('Please provide valid coordinates.'); + } else { + $.getJSON("/api/geocode", { parse: parseCoords}, function (response) { + if (response.status == "success") { + var newLatLng = new LatLon(response.data.lat, response.data.lng); + + // update the displayed coords + var dist = curLatLng.rhumbDistanceTo(newLatLng); + var bearingTo = curLatLng.rhumbBearingTo(newLatLng); + var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N"; + + var formats = response.data.formats; + // all these finds, make me feel dirty + $menu + .find("span.ccu-parseverify-coords").text(formats.DM).end() + .find("dl.ccu-parse").hide().end() + .find("dl.ccu-parseverify").show().end() + .find("button.ccu-parseverify-accept") + .data("utm", '') + .data("dm", formats.DM) + .data("lat", response.data.lat) + .data("lng", response.data.lng) + .end(); + } else { + alert("Sorry unable to parse the coordinates you entered."); + } + }); + } + + return false; + }); + + $menu.delegate("button.ccu-parseverify-accept", "click", function (e) { + e.preventDefault(); + var $this = $(this); + // update to webmethod + $.pageMethod("/seek/cache_details.aspx/SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } else { + $("#uxLatLonLink").qtip('hide'); + } + + }); + + return false; + }); + + $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) { + e.preventDefault(); + $menu + .find("input.cc-parse-text").val('').end() + .find("dl.ccu-parse").show().end() + .find("dl.ccu-parseverify").hide().end(); + return false; + }); + + $menu.delegate("a.ccu-restore", "click", function (e) { + e.preventDefault(); + + $.pageMethod("/seek/cache_details.aspx/ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } + }); + + return false; + }); + + return $menu; + } + + GSPK = window.GSPK || {}; + GSPK.Selector = {}; + GSPK.Selector.getSelected = function(){ + var t = null; + if ( window.getSelection ){ + t = window.getSelection(); + }else if(document.getSelection){ + t = document.getSelection(); + }else if(document.selection){ + t = document.selection.createRange().text; + } + return t; + } + //--> + </script> + <script id="loc_favPointsScoreDesc" type="text/html"> + Favorites/Premium Logs + </script> + <script type="text/javascript" language="javascript"> + <!-- + var gotScore = false; + var favDropDown = $('.favorite-dropdown'); + var favContainer = $('.favorite-container'); + + function showFavoriteScore() { + $('#imgFavoriteScore').attr('src', '/images/loading3.gif'); + + $('#uxFavoriteScore').parent().fadeTo(200, .001, function () { + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/score?u=' + userToken, + success: function (scoreResult) { + gotScore = true; + + var score = 0; + + if(scoreResult) { + score = scoreResult; + } + + if(score > 100) { + score = 100; + } + + $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png'); + var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim(); + $('#imgFavoriteScore').attr('alt', pieDesc); + $('#imgFavoriteScore').attr('title', pieDesc); + + $('#uxFavoriteScore').parent().fadeTo(1000, 1); + $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html()); + } + }); + }); + } + var scrollId = false, + logTop = 0; + + if (document.getElementById("cache_logs_container") != null){ + logTop = $("#cache_logs_container").position().top; + } + + + $(window).on("scroll", function() { + if (scrollId != false) { + window.clearTimeout(scrollId); + scrollId = false; + } + + scrollId = window.setTimeout(function() { + if (showScroll){ + if ($(this).scrollTop()< logTop) { + $("#topScroll").fadeOut(); + } else { + $("#topScroll").fadeIn(); + } + }}, 250); + }); + + $(document).bind('mouseup', function (e) { + var $clicked = $(e.target); + if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) { + favDropDown.hide(1, function () { + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + }); + } + }); + + $('#uxFavContainerLink').click(function () { + if ($(favDropDown).is(':visible')) { + favDropDown.hide(1, function(){ + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + }); + } + else { + if (!gotScore) { + showFavoriteScore(); + } + + favContainer.addClass('favorite-container-open'); + favContainer.removeClass('favorite-container'); + favDropDown.show(1); + } + }); + + // End --> + </script> - scrollId = window.setTimeout(function() {
- if (showScroll){
- if ($(this).scrollTop()< logTop) {
- $("#topScroll").fadeOut();
- } else {
- $("#topScroll").fadeIn();
- }
- }}, 250);
- });
-
- $(document).bind('mouseup', function (e) {
- var $clicked = $(e.target);
- if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) {
- favDropDown.hide(1, function () {
- favContainer.addClass('favorite-container');
- favContainer.removeClass('favorite-container-open');
- });
- }
- if ($('#log-dropdown-options').is(':visible') && !$clicked.parents().hasClass('Dropdown')){
- $('#log-dropdown-options').toggleClass('hideMe');
- $('.Dropdown').toggleClass('Active');
- }
- });
- $('#uxFavContainerLink').click(function () {
- if ($(favDropDown).is(':visible')) {
- favDropDown.hide(1, function(){
- favContainer.addClass('favorite-container');
- favContainer.removeClass('favorite-container-open');
- });
- }
- else {
- if (!gotScore) {
- showFavoriteScore();
- }
+ <script type="text/javascript">
- favContainer.addClass('favorite-container-open');
- favContainer.removeClass('favorite-container');
- favDropDown.show(1);
- }
- });
- $('#dropdown-arrow').on('click', function(e){
- e.preventDefault();
- $('#log-dropdown-options').toggleClass('hideMe');
- $('.Dropdown').toggleClass('Active');
- });
- // End -->
- </script>
-
- <script type="text/javascript">
$(document).ready(function () {
$('#hlUpgrade').bind('click', function () {
var _this = $(this);
@@ -2042,52 +1919,45 @@ var gaToken = 'UA-2020240-1';//]]> return false;
});
});
- </script>
- <script type="text/javascript">
+
+
+ _gaq.push(['_setCustomVar', 1, 'AccountId', 3409138, 1]);
+
+
_gaq.push(['_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js']);
_gaq.push(['_setAccount', gaToken]);
_gaq.push(['_trackPageview']);
- (function () {
- var ga = document.createElement('script');
- ga.src = ('https:' == document.location.protocol ?
- 'https://ssl' : 'http://www') +
- '.google-analytics.com/ga.js';
- ga.setAttribute('async', 'true');
- document.documentElement.firstChild.appendChild(ga);
- })();
+
$(function () {
$("a.language").click(function (e) {
e.preventDefault();
window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
});
});
- </script>
- <!-- Quantcast Tag -->
- <div id="Quantcast">
- <script type="text/javascript">
- var _qevents = _qevents || [];
- (function () {
- var elem = document.createElement('script');
+ var _qevents = _qevents || [];
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
- elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
- elem.async = true;
- elem.type = "text/javascript";
- var scpt = document.getElementsByTagName('script')[0];
- scpt.parentNode.insertBefore(elem, scpt);
- })();
- </script>
- <script type="text/javascript">
- _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
- </script>
- <noscript>
- <div style="display: none;">
- <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
- alt="Quantcast" />
- </div>
- </noscript>
- </div>
- <!-- End Quantcast tag -->
- <!-- Server: WEB17; Build: Web.HotFix_20130821.1 -->
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+
+
+
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" />
+ </div>
+ </noscript>
+ <!-- Server: WEB07; Build: Tucson.Main.release-20150330.1.Release_270
+ -->
</body>
</html>
diff --git a/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java b/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java index 09139f2..4d74792 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java +++ b/tests/src/cgeo/geocaching/test/mock/GC1ZXX2.java @@ -4,7 +4,9 @@ import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; + +import org.eclipse.jdt.annotation.NonNull; import java.text.ParseException; import java.util.Date; @@ -38,6 +40,7 @@ public class GC1ZXX2 extends MockedCache { return "Rich Uncle Pennybags"; } + @NonNull @Override public CacheSize getSize() { return CacheSize.OTHER; @@ -58,6 +61,7 @@ public class GC1ZXX2 extends MockedCache { return true; } + @NonNull @Override public String getOwnerUserId() { return "daniel354"; @@ -86,13 +90,14 @@ public class GC1ZXX2 extends MockedCache { @Override public Date getHiddenDate() { try { - return GCLogin.parseGcCustomDate("16/10/2009", getDateFormat()); + return GCLogin.parseGcCustomDate("2009-10-16", getDateFormat()); } catch (ParseException e) { // intentionally left blank } return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { diff --git a/tests/src/cgeo/geocaching/test/mock/GC2CJPF.html b/tests/src/cgeo/geocaching/test/mock/GC2CJPF.html index ea96e8c..0a6f8ed 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2CJPF.html +++ b/tests/src/cgeo/geocaching/test/mock/GC2CJPF.html @@ -4,23 +4,19 @@ <html lang="en" class="no-js">
<head id="ctl00_Head1"><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><title>
GC2CJPF Kinderwald KiC (Multi-cache) in Niedersachsen, Germany created by Tom03
-</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" />
- <!--[if lt IE 8]>
- <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" />
- <![endif]-->
- <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" />
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta id="ctl00_ogUrl" property="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC2CJPF&title=kinderwald-kic" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="Geocaching: the anytime, anywhere outdoor adventure game." /><meta name="twitter:description" content="There are millions of geocaches worldwide and probably even some near you right now. Visit Geocaching.com to see just how many geocaches are nearby and to get the free Official Geocaching app." /><meta name="twitter:image:src" content="https://www.geocaching.com/play/Content/images/preview-lg.jpg" /><meta name="author" content="Geocaching" /><meta name="DC.creator" content="Geocaching" /><meta name="Copyright" content="Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta name="p:domain_verify" content="107f8f596a30ff1ea307df82db696a5e" /><link href="//fonts.googleapis.com/css?family=Noto+Sans:400,700&subset=latin,latin-ext" rel="stylesheet" type="text/css" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link href="/content/coreCSS?v=LW0HKwsIsnIiQyE_ovDSvnj5M2xR0XjkVV3GaTHUlRI1" rel="stylesheet"/>
+<link href="/css/jqueryui1104/jqUI?v=G2XN-0HsvYJqSZehzmbzhJiIBnEZ9PaVHVjIweqiSx41" rel="stylesheet"/>
+<link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" /><script src="/bundle/modernizer?v=q--nrqGQx_uxNYSvw1AFPQRWLPih7RGk2o0lu9veYaY1"></script>
+<script src="/bundle/coreJS?v=uKjd3XRiFC1C29gkUc0JuDRCF6PuUu7R8PpzGjgXDEc1"></script>
+
+
<script type="text/javascript">
- var _gaq = _gaq || [];
- </script>
- <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script>
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
-
- <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js" type="text/javascript"></script>
- <script type="text/javascript" src="/js/jquery.truncate.min.js"></script>
-
- <script type='text/javascript'>
+
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
+
+ var _gaq = _gaq || [];
+
(function () {
var gads = document.createElement('script');
gads.async = true;
@@ -30,49 +26,68 @@ var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
- </script>
-
-
-
- <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" />
- <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" />
- <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" />
- <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.css" />
- <!--[if IE]>
- <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.ie.css" />
- <![endif]-->
- <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" />
- <script type="text/javascript" src="/js/leaflet/0.5.1/leaflet.js"></script>
- <script type="text/javascript" src="/js/geometa.js"></script>
- <script type="text/javascript">
- var userToken = null,
- urlParams = {},
- mapLatLng = null,
- cmapAdditionalWaypoints = [],
- initalLogs = null, totalLogs = 0, includeAvatars = false;
+ (function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments);
+ }, i[r].l = 1 * new Date();
+ a = s.createElement(o),
+ m = s.getElementsByTagName(o)[0];
+ a.async = 1; a.src = g;
+ m.parentNode.insertBefore(a, m);
+ })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
(function () {
- var e,
- d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); },
- q = window.location.search.substring(1),
- r = /([^&=]+)=?([^&]*)/g;
- while (e = r.exec(q)) {
- urlParams[d(e[1])] = d(e[2]);
- }
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+
})();
+
</script>
-<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC2CJPF&title=kinderwald-kic&Submit6=Go" property="og:url" /><meta name="og:description" content="Use a smartphone or GPS device to navigate to the provided coordinates, which will then lead you to one or more locations. Look for a small hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 2 and difficulty is 2.5 (out of 5)." property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/3.png" property="og:image" /><meta name="og:title" content="Kinderwald KiC" property="og:title" /><script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="description" content="Kinderwald KiC (GC2CJPF) was created by Tom03 on 07/31/2010. It's a Small size geocache, with difficulty of 2.5, terrain of 2. It's located in Niedersachsen, Germany.Von Nachwuchs-Cachern für Nachwuchs-Cacher. Kleiner Multi über 7 Stationen. Länge ca. 1 km + 1km für den Rückweg. Die ZS befinden sich alle am KLEINEN BACH innerhalb des Kinderwaldes." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
+ + + + <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" /> + <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" /> + <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" /> + <link rel="stylesheet" type="text/css" media="all" href="/static/js/leaflet/0.7.2/leaflet.css" /> + <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" /> + <script type="text/javascript" src="/static/js/leaflet/0.7.2/leaflet.js"></script> + <script type="text/javascript"> + var userToken = null, + urlParams = {}, + mapLatLng = null, + cmapAdditionalWaypoints = [], + initalLogs = null, totalLogs = 0, includeAvatars = false; + + (function () { + var e, + d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); }, + q = window.location.search.substring(1), + r = /([^&=]+)=?([^&]*)/g; + + while (e = r.exec(q)) { + urlParams[d(e[1])] = d(e[2]); + } + })(); + </script> +<script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:description" content="Use a smartphone or GPS device to navigate to the provided coordinates, which will then lead you to one or more locations. Look for a small hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 2 and difficulty is 2.5 (out of 5)." property="og:description" /><meta name="og:title" content="Kinderwald KiC" property="og:title" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/3.png" property="og:image" /><meta name="description" content="Kinderwald KiC (GC2CJPF) was created by Tom03 on 07/31/2010. It's a Small size geocache, with difficulty of 2.5, terrain of 2. It's located in Niedersachsen, Germany.Von Nachwuchs-Cachern für Nachwuchs-Cacher. Kleiner Multi über 7 Stationen. Länge ca. 1 km + 1km für den Rückweg. Die ZS befinden sich alle am KLEINEN BACH innerhalb des Kinderwaldes." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
<body background="http://www.blafoo.de/images/Kinderwald.jpg" class="CacheDetailsPage">
- <form name="aspnetForm" method="post" action="/geocache/GC2CJPF_kinderwald-kic?Submit6=Go" id="aspnetForm">
+ <form name="aspnetForm" method="post" action="/geocache/GC2CJPF_kinderwald-kic" id="aspnetForm">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="3" />
-<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE1Mzk0NTE5MTEPFgIeBEMuSUQoKVlTeXN0ZW0uSW50NjQsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQcxODExNDA5FgJmD2QWBmYPZBYKAgYPFgIeBFRleHQFYjxtZXRhIG5hbWU9IkNvcHlyaWdodCIgY29udGVudD0iQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4iIC8+ZAIHDxYCHwEFRzwhLS0gQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4gLS0+ZAIZDxYCHgRocmVmBR1+L2Nzcy90bG5NYXN0ZXJTY3JlZW4uY3NzP3I9MWQCGg8WAh8CBRV+L2Nzcy90bG5NYWluLmNzcz9yPTFkAh8PFgIeB1Zpc2libGVoZAIBDxYCHgZhY3Rpb24FKy9nZW9jYWNoZS9HQzJDSlBGX2tpbmRlcndhbGQta2ljP1N1Ym1pdDY9R28WFgILDxYCHwFkZAIND2QWAgIFDxYCHwNnFggCAQ8PFgIeCEltYWdlVXJsBU5odHRwOi8vaW1nLmdlb2NhY2hpbmcuY29tL3VzZXIvYXZhdGFyL2U4YTk3YTA1LWEwNTEtNGRhOS1iYzkzLTZhODMwYjg2NmFmZi5qcGdkZAIDDxYCHwEFbEhlbGxvLCA8YSBocmVmPSIvbXkvZGVmYXVsdC5hc3B4IiB0aXRsZT0iVmlldyBQcm9maWxlIGZvciBKb1NhTWFKYSIgY2xhc3M9IlNpZ25lZEluUHJvZmlsZUxpbmsiPkpvU2FNYUphPC9hPmQCBQ8PFgIeC05hdmlnYXRlVXJsBa4BaHR0cHM6Ly93d3cuZ2VvY2FjaGluZy5jb20vbG9naW4vZGVmYXVsdC5hc3B4P1JFU0VUPVkmcmVkaXI9aHR0cCUzYSUyZiUyZnd3dy5nZW9jYWNoaW5nLmNvbSUyZnNlZWslMmZjYWNoZV9kZXRhaWxzLmFzcHglM2Z3cCUzZEdDMkNKUEYlMjZ0aXRsZSUzZGtpbmRlcndhbGQta2ljJTI2U3VibWl0NiUzZEdvZGQCCw8WAh8BBRA0ODQgQ2FjaGVzIEZvdW5kZAIXDxYCHwNnFgICDQ8PFgIfBgVAfi90cmFjay9zZWFyY2guYXNweD9vPTEmdWlkPTRkNDE2NDYxLWQxYTctNGNjNS04ZWU3LTMzNmJiOTEwZmViOGRkAh0PDxYCHwNnZGQCKQ8WAh8DZ2QCVw9kFgQCAw8WAh8BBQdFbmdsaXNoZAIFDxYCHgtfIUl0ZW1Db3VudAIUFihmD2QWAgIBDw8WCB4PQ29tbWFuZEFyZ3VtZW50BQVlbi1VUx4LQ29tbWFuZE5hbWUFDVNldFRlbXBMb2NhbGUfAQUHRW5nbGlzaB4QQ2F1c2VzVmFsaWRhdGlvbmhkZAIBD2QWAgIBDw8WCB8IBQVkZS1ERR8JBQ1TZXRUZW1wTG9jYWxlHwEFB0RldXRzY2gfCmhkZAICD2QWAgIBDw8WCB8IBQVmci1GUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUZyYW7Dp2Fpcx8KaGRkAgMPZBYCAgEPDxYIHwgFBXB0LVBUHwkFDVNldFRlbXBMb2NhbGUfAQUKUG9ydHVndcOqcx8KaGRkAgQPZBYCAgEPDxYIHwgFBWNzLUNaHwkFDVNldFRlbXBMb2NhbGUfAQUJxIxlxaF0aW5hHwpoZGQCBQ9kFgICAQ8PFggfCAUFZGEtREsfCQUNU2V0VGVtcExvY2FsZR8BBQVEYW5zax8KaGRkAgYPZBYCAgEPDxYIHwgFBXN2LVNFHwkFDVNldFRlbXBMb2NhbGUfAQUHU3ZlbnNrYR8KaGRkAgcPZBYCAgEPDxYIHwgFBWVzLUVTHwkFDVNldFRlbXBMb2NhbGUfAQUIRXNwYcOxb2wfCmhkZAIID2QWAgIBDw8WCB8IBQVldC1FRR8JBQ1TZXRUZW1wTG9jYWxlHwEFBUVlc3RpHwpoZGQCCQ9kFgICAQ8PFggfCAUFaXQtSVQfCQUNU2V0VGVtcExvY2FsZR8BBQhJdGFsaWFubx8KaGRkAgoPZBYCAgEPDxYIHwgFBWVsLUdSHwkFDVNldFRlbXBMb2NhbGUfAQUQzpXOu867zrfOvc65zrrOrB8KaGRkAgsPZBYCAgEPDxYIHwgFBWx2LUxWHwkFDVNldFRlbXBMb2NhbGUfAQUJTGF0dmllxaF1HwpoZGQCDA9kFgICAQ8PFggfCAUFbmwtTkwfCQUNU2V0VGVtcExvY2FsZR8BBQpOZWRlcmxhbmRzHwpoZGQCDQ9kFgICAQ8PFggfCAUFY2EtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQdDYXRhbMOgHwpoZGQCDg9kFgICAQ8PFggfCAUFcGwtUEwfCQUNU2V0VGVtcExvY2FsZR8BBQZQb2xza2kfCmhkZAIPD2QWAgIBDw8WCB8IBQVuYi1OTx8JBQ1TZXRUZW1wTG9jYWxlHwEFDk5vcnNrLCBCb2ttw6VsHwpoZGQCEA9kFgICAQ8PFggfCAUFa28tS1IfCQUNU2V0VGVtcExvY2FsZR8BBQntlZzqta3slrQfCmhkZAIRD2QWAgIBDw8WCB8IBQVodS1IVR8JBQ1TZXRUZW1wTG9jYWxlHwEFBk1hZ3lhch8KaGRkAhIPZBYCAgEPDxYIHwgFBXJvLVJPHwkFDVNldFRlbXBMb2NhbGUfAQUIUm9tw6JuxIMfCmhkZAITD2QWAgIBDw8WCB8IBQVqYS1KUB8JBQ1TZXRUZW1wTG9jYWxlHwEFCeaXpeacrOiqnh8KaGRkAlsPZBYCAgMPFgIfA2hkAl0PFgIeBWNsYXNzBQxzcGFuLTI0IGxhc3QWAgIBD2QWKAIBD2QWAmYPZBYCAgEPDxYCHwEFB0dDMkNKUEZkZAICDxYCHwEFmgE8YSBocmVmPSIvYWJvdXQvY2FjaGVfdHlwZXMuYXNweCIgdGFyZ2V0PSJfYmxhbmsiIHRpdGxlPSJBYm91dCBDYWNoZSBUeXBlcyI+PGltZyBzcmM9Ii9pbWFnZXMvV3B0VHlwZXMvMy5naWYiIGFsdD0iTXVsdGktY2FjaGUiIHRpdGxlPSJNdWx0aS1jYWNoZSIgLz48L2E+ZAIGD2QWBAIBDxYCHwNnZAIHDxYCHwNoZAIKD2QWBgIBDxYCHwEFAjIyZAIFDxYCHwNoZAIHDw8WAh8GBUQvc2Vlay9jYWNoZV9mYXZvcml0ZWQuYXNweD9ndWlkPTczMjQ2YTVhLWViYjktNGQ0Zi04ZGI5LWE5NTEwMzZmNTM3NmRkAgwPDxYCHwYFGWh0dHA6Ly93d3cua2luZGVyd2FsZC5kZS9kZAIPDxYCHwNoZAIQDxYCHwNoZAIRD2QWDAIDD2QWAgIBDxYCHwEFG1VUTTogMzJVIEUgNTQ1MTY0IE4gNTgwODUyNGQCDQ8PFgIfBgUzY2RwZi5hc3B4P2d1aWQ9NzMyNDZhNWEtZWJiOS00ZDRmLThkYjktYTk1MTAzNmY1Mzc2ZGQCDw8PFgIfBgU4Y2RwZi5hc3B4P2d1aWQ9NzMyNDZhNWEtZWJiOS00ZDRmLThkYjktYTk1MTAzNmY1Mzc2JmxjPTVkZAIRDw8WAh8GBTljZHBmLmFzcHg/Z3VpZD03MzI0NmE1YS1lYmI5LTRkNGYtOGRiOS1hOTUxMDM2ZjUzNzYmbGM9MTBkZAITDw8WBB8GBXRodHRwOi8vbWFwcy5nb29nbGUuY29tL21hcHM/Zj1kJmhsPWVuJnNhZGRyPTUyLjIxNjI1LDkuNzE0NDgzIChIb21lIExvY2F0aW9uKSZkYWRkcj01Mi40MjUwNjcsOS42NjQyKEtpbmRlcndhbGQrS2lDKR4GVGFyZ2V0BQZfYmxhbmtkZAIbD2QWCGYPDxYEHglGb3JlQ29sb3IMHgRfIVNCAgRkZAIBDw8WBB8NDB8OAgRkZAICDw8WAh8DZxYCHgdvbmNsaWNrBTtzMmdwcygnNzMyNDZhNWEtZWJiOS00ZDRmLThkYjktYTk1MTAzNmY1Mzc2Jyk7cmV0dXJuIGZhbHNlO2QCAw8PFgIfA2cWAh8PBSBzMnBob25lKCdHQzJDSlBGJyk7cmV0dXJuIGZhbHNlO2QCEw8WAh8DZ2QCFw9kFghmDxYCHwNoZAIBDw8WAh8DaGRkAgIPDxYCHwNoZGQCAw8WAh8DaGQCGA9kFgICAw8PFgIfAQUHRGVjcnlwdGRkAhkPFgIfAQUbUW5mIFN2YW55IHZmZyBoYWdyZSBGZ3J2YXJhZAIbD2QWBAIBDxYEHwIFHy9zZWVrL2xvZy5hc3B4P0lEPTE4MTE0MDkmbGNuPTEeCWlubmVyaHRtbAUOTG9nIHlvdXIgdmlzaXRkAgIPFgIfA2hkAhwPFgIfA2dkAh0PFgIfA2hkAiAPZBYCAgMPFgIfEAUTQWR2ZXJ0aXNpbmcgd2l0aCBVc2QCJA9kFgQCBQ8PFgIfA2dkZAIJDw8WAh8GBTx+L3RyYWNrL3NlYXJjaC5hc3B4P3dpZD03MzI0NmE1YS1lYmI5LTRkNGYtOGRiOS1hOTUxMDM2ZjUzNzZkZAIlDw8WAh8DZ2QWAmYPFgIfBwIBFgICAQ9kFgJmDxUCAOMBPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9ib29rbWFya3Mvdmlldy5hc3B4P2d1aWQ9M2VlZWEwNTctZjYwNS00ODVhLWE0NWEtZjVmZWExNDI2NjEyIj5LaW5kZXJjYWNoZXMgKEtpQyk8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD0wNTY0YTk0MC04MzExLTQwZWUtOGU3Ni03ZTkxYjJjZjYyODQi" />
-<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="PmJsYWZvbzwvYT5kAiYPDxYCHwNnZBYCZg8WAh8HAgEWAgIBD2QWAmYPFQIA3QE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD0xNDU1MTcwOC0wYzNjLTRmOTUtOTM0Mi0xYmIzMTE5ZTZlZmUiPmNnZW8gbW9ja3M8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD00ZDQxNjQ2MS1kMWE3LTRjYzUtOGVlNy0zMzZiYjkxMGZlYjgiPkpvU2FNYUphPC9hPmQCJw9kFhACAw9kFgICAQ8PFgIfBgVFL2hpZGUvd3B0bGlzdC5hc3B4P1JlZldwdElEPTczMjQ2YTVhLWViYjktNGQ0Zi04ZGI5LWE5NTEwMzZmNTM3NiZEUz0xZGQCBw8PFgQeBlJEUy5JRAspdkdyb3VuZHNwZWFrLldlYi5HUFguV3B0RGF0YVNvdXJjZXMsIFR1Y3Nvbi5Db21tb24uTGVnYWN5LCBWZXJzaW9uPTMuMC40OTgxLjEzMjkzLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPW51bGwBHgdSV1BULklEKCsEBzE4MTE0MDlkFgJmDxYCHwcCBBYKZg9kFgJmDw8WAh8DaGRkAgEPZBYOZg8VAgAFZmFsc2VkAgIPFQd0PGltZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHNyYz0iL2ltYWdlcy9pY29ucy9pY29uX25vY29vcmRzLmpwZyIgYWx0PSJIaWRlIENvb3JkaW5hdGVzIiB0aXRsZT0iSGlkZSBDb29yZGluYXRlcyIgLz6GATxpbWcgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBzcmM9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vaW1hZ2VzL3dwdHR5cGVzL3NtL2ZsYWcuanBnIiBhbHQ9IkZpbmFsIExvY2F0aW9uIiB0aXRsZT0iRmluYWwgTG9jYXRpb24iIC8+AkZOAkZOBUZJTkFMsAE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3NlZWsvd3B0LmFzcHg/V0lEPTMwZjFiMzdjLWQzOTUtNGM3YS05NGUyLTBjNjQ5ZDVmMjMxYiZSZWZJRD03MzI0NmE1YS1lYmI5LTRkNGYtOGRiOS1hOTUxMDM2ZjUzNzYmUmVmRFM9MSI+R0MyQ0pQRiBGaW5hbDwvYT4gKEZpbmFsIExvY2F0aW9uKQM/Pz9kAgUPDxYCHgdUb29sVGlwBQRFZGl0ZGQCBw8PFgIfEwUDTWFwZGQCCw8PFgIeDUFsdGVybmF0ZVRleHQFBlJlbW92ZRYCHw8FQHJldHVybiBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmVtb3ZlIHRoaXMgd2F5cG9pbnQ/JylkAgwPFQEAZAIODxUBAGQCAg9kFg5mDxUCDkFsdGVybmF0aW5nUm93BWZhbHNlZAICDxUHYjxpbWcgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBzcmM9Ii9pbWFnZXMvaWNvbnMvaWNvbl92aWV3YWJsZS5qcGciIGFsdD0iVmlzaWJsZSIgdGl0bGU9IlZpc2libGUiIC8+gQE8aW1nIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgc3JjPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2ltYWdlcy93cHR0eXBlcy9zbS9wa2cuanBnIiBhbHQ9IlBhcmtpbmcgQXJlYSIgdGl0bGU9IlBhcmtpbmcgQXJlYSIgLz4CUEsCUEsGUEFSS05HsAE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3NlZWsvd3B0LmFzcHg/V0lEPTk4Y2IxMzg3LTQ5Y2UtNGY5NC05YjA1LTVjYjA3OWQzMzJiMSZSZWZJRD03MzI0NmE1YS1lYmI5LTRkNGYtOGRiOS1hOTUxMDM2ZjUzNzYmUmVmRFM9MSI+R0MyQ0pQRiBQYXJraW5nPC9hPiAoUGFya2luZyBBcmVhKRxOIDUywrAgMjUuMzg0IEUgMDA5wrAgMzkuMDIzZAIFDw8WAh8TBQRFZGl0ZGQCBw8PFgIfEwUDTWFwZGQCCw8PFgIfFAUGUmVtb3ZlFgIfDwVAcmV0dXJuIGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyB3YXlwb2ludD8nKWQCDA8VAQ5BbHRlcm5hdGluZ1Jvd2QCDg8VATdLZWluICJvZmZpemllbGxlciIgUGFya3BsYXR6LCBQYXJrZW4gdHJvdHpkZW0gbcO2Z2xpY2guZAIDD2QWDmYPFQIABWZhbHNlZAICDxUHYjxpbWcgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBzcmM9Ii9pbWFnZXMvaWNvbnMvaWNvbl92aWV3YWJsZS5qcGciIGFsdD0iVmlzaWJsZSIgdGl0bGU9IlZpc2libGUiIC8+kAE8aW1nIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgc3JjPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2ltYWdlcy93cHR0eXBlcy9zbS9wdXp6bGUuanBnIiBhbHQ9IlF1ZXN0aW9uIHRvIEFuc3dlciIgdGl0bGU9IlF1ZXN0aW9uIHRvIEFuc3dlciIgLz4CU1QCU1QFU1RBUlS0ATxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vc2Vlay93cHQuYXNweD9XSUQ9MDQxMTNiYWQtNjRjYS00OTlhLTk4NDgtYjU5MzdlMTNkYTFiJlJlZklEPTczMjQ2YTVhLWViYjktNGQ0Zi04ZGI5LWE5NTEwMzZmNTM3NiZSZWZEUz0xIj5HQzJDSlBGIFN0YXJ0PC9hPiAoUXVlc3Rpb24gdG8gQW5zd2VyKRxOIDUywrAgMjUuNTA0IEUgMDA5wrAgMzkuODUyZAIFDw8WAh8TBQRFZGl0ZGQCBw8PFgIfEwUDTWFwZGQCCw8PFgIfFAUGUmVtb3ZlFgIfDwVAcmV0dXJuIGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyB3YXlwb2ludD8nKWQCDA8VAQBkAg4PFQEAZAIED2QWDmYPFQIOQWx0ZXJuYXRpbmdSb3cFZmFsc2VkAgIPFQdiPGltZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHNyYz0iL2ltYWdlcy9pY29ucy9pY29uX3ZpZXdhYmxlLmpwZyIgYWx0PSJWaXNpYmxlIiB0aXRsZT0iVmlzaWJsZSIgLz6MATxpbWcgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBzcmM9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vaW1hZ2VzL3dwdHR5cGVzL3NtL3dheXBvaW50LmpwZyIgYWx0PSJSZWZlcmVuY2UgUG9pbnQiIHRpdGxlPSJSZWZlcmVuY2UgUG9pbnQiIC8+AldPAldPBlNDRU5JQ7IBPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9zZWVrL3dwdC5hc3B4P1dJRD1iMjhjNTg3OS0zMTgxLTQ1MTAtOTRmYS02ZWM1ZTMwZmQwNTYmUmVmSUQ9NzMyNDZhNWEtZWJiOS00ZDRmLThkYjktYTk1MTAzNmY1Mzc2JlJlZkRTPTEiPkF1c3NpY2h0c3B1bmt0PC9hPiAoUmVmZXJlbmNlIFBvaW50KRxOIDUywrAgMjUuNDg4IEUgMDA5wrAgMzkuNDMyZAIFDw8WAh8TBQRFZGl0ZGQCBw8PFgIfEwUDTWFwZGQCCw8PFgIfFAUGUmVtb3ZlFgIfDwVAcmV0dXJuIGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyB3YXlwb2ludD8nKWQCDA8VAQ5BbHRlcm5hdGluZ1Jvd2QCDg8VAU9FaGVtYWxpZ2UgRmluYWxsb2NhdGlvbiB3byBlcyBnZWJyYW5udCBoYXQuIEdsZWljaHplaXRpZyBuZXR0ZXIgQXVzc2ljaHRzcHVua3QuZAIJDw8WAh8DZ2QWAgIBDw8WBB8GBSovbWFwL2RlZmF1bHQuYXNweD9sYXQ9NTIuNDI1MDY3JmxuZz05LjY2NDIfA2dkZAIPDxYCHwEFfy4uLm90aGVyIGNhY2hlcyA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dT1Ub20wMyI+aGlkZGVuPC9hPiBvciA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dWw9VG9tMDMiPmZvdW5kPC9hPiBieSB0aGlzIHVzZXJkAhEPZBYGAgEPFgIfAQX/AS4uLm5lYXJieSA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dHg9YTVmNmQwYWQtZDJmMi00MDExLThjMTQtOTQwYTllYmYzYzc0JmxhdD01Mi40MjUwNjcmbG5nPTkuNjY0MjAwIj5jYWNoZXMgb2YgdGhpcyB0eXBlPC9hPiwgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P3R4PWE1ZjZkMGFkLWQyZjItNDAxMS04YzE0LTk0MGE5ZWJmM2M3NCZsYXQ9NTIuNDI1MDY3JmxuZz05LjY2NDIwMCZmPTEiPnRoYXQgSSBoYXZlbid0IGZvdW5kPC9hPmQCAw8WAh8BBaYBLi4uYWxsIG5lYXJieSA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/bGF0PTUyLjQyNTA2NyZsbmc9OS42NjQyMDAiPmNhY2hlczwvYT4sIDxhIGhyZWY9Ii9zZWVrL25lYXJlc3QuYXNweD9sYXQ9NTIuNDI1MDY3JmxuZz05LjY2NDIwMCZmPTEiPnRo" />
-<input type="hidden" name="__VIEWSTATE2" id="__VIEWSTATE2" value="YXQgSSBoYXZlbid0IGZvdW5kPC9hPmQCBQ8WAh8BBX4uLi5hbGwgbmVhcmJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cud2F5bWFya2luZy5jb20vZGlyZWN0b3J5LmFzcHg/Zj0xJmxhdD01Mi40MjUwNjcmbG9uPTkuNjY0MjAwIj53YXltYXJrcyBvbiBXYXltYXJraW5nLmNvbTwvYT5kAhMPFgIfA2hkAhcPZBYCAgEPDxYEHwEFrgc8bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9tYXAvZGVmYXVsdC5hc3B4P2xhdD01Mi40MjUwNyZsbmc9OS42NjQyIiB0YXJnZXQ9Il9ibGFuayI+R2VvY2FjaGluZy5jb20gTWFwPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly9tYXBzLmdvb2dsZS5jb20vbWFwcz9xPU4rNTIlYzIlYjArMjUuNTA0K0UrMDA5JWMyJWIwKzM5Ljg1MisoR0MyQ0pQRikrIiB0YXJnZXQ9Il9ibGFuayI+R29vZ2xlIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5tYXBxdWVzdC5jb20vbWFwcy9tYXAuYWRwP3NlYXJjaHR5cGU9YWRkcmVzcyZmb3JtdHlwZT1sYXRsb25nJmxhdGxvbmd0eXBlPWRlY2ltYWwmbGF0aXR1ZGU9NTIuNDI1MDcmbG9uZ2l0dWRlPTkuNjY0MiZ6b29tPTEwIiB0YXJnZXQ9Il9ibGFuayI+TWFwUXVlc3Q8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL21hcHMueWFob28uY29tLyNsYXQ9NTIuNDI1MDcmbG9uPTkuNjY0MiZ6b29tPTE2JnE9NTIuNDI1MDcsOS42NjQyJmNvbmY9MSZzdGFydD0xJm12dD1tJnRyZj0wIiB0YXJnZXQ9Il9ibGFuayI+WWFob28gTWFwczwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vd3d3LmJpbmcuY29tL21hcHMvZGVmYXVsdC5hc3B4P3Y9MiZsdmw9MTQmc3A9cG9pbnQuNTIuNDI1MDdfOS42NjQyX0dDMkNKUEYiIHRhcmdldD0iX2JsYW5rIj5CaW5nIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5vcGVuY3ljbGVtYXAub3JnLz96b29tPTEyJmxhdD01Mi40MjUwNyZsb249OS42NjQyIiB0YXJnZXQ9Il9ibGFuayI+T3BlbkN5Y2xlTWFwPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvP21sYXQ9NTIuNDI1MDcmbWxvbj05LjY2NDImem9vbT0xMiIgdGFyZ2V0PSJfYmxhbmsiPk9wZW5TdHJlZXRNYXA8L2E+PC9saT4fA2dkZAIbD2QWBgIBDxYCHwEFETE3MSBMb2dnZWQgVmlzaXRzZAIHDw8WAh8GBUN+L3NlZWsvY2FjaGVfbG9nYm9vay5hc3B4P2d1aWQ9NzMyNDZhNWEtZWJiOS00ZDRmLThkYjktYTk1MTAzNmY1Mzc2ZGQCCQ8PFgQfBgU9fi9zZWVrL2dhbGxlcnkuYXNweD9ndWlkPTczMjQ2YTVhLWViYjktNGQ0Zi04ZGI5LWE5NTEwMzZmNTM3Nh8BBSNWaWV3IHRoZSBJbWFnZSBHYWxsZXJ5IG9mIDE3IGltYWdlc2RkAl8PFgIfA2gWAgIBDw9kFgIeBXN0eWxlBQx3aWR0aDoxMjBweDtkAmEPZBYEAgMPFgIfAQUHRW5nbGlzaGQCBQ8WAh8HAhQWKGYPZBYCAgEPDxYIHwgFBWVuLVVTHwkFDVNldFRlbXBMb2NhbGUfAQUHRW5nbGlzaB8KaGRkAgEPZBYCAgEPDxYIHwgFBWRlLURFHwkFDVNldFRlbXBMb2NhbGUfAQUHRGV1dHNjaB8KaGRkAgIPZBYCAgEPDxYIHwgFBWZyLUZSHwkFDVNldFRlbXBMb2NhbGUfAQUJRnJhbsOnYWlzHwpoZGQCAw9kFgICAQ8PFggfCAUFcHQtUFQfCQUNU2V0VGVtcExvY2FsZR8BBQpQb3J0dWd1w6pzHwpoZGQCBA9kFgICAQ8PFggfCAUFY3MtQ1ofCQUNU2V0VGVtcExvY2FsZR8BBQnEjGXFoXRpbmEfCmhkZAIFD2QWAgIBDw8WCB8IBQVkYS1ESx8JBQ1TZXRUZW1wTG9jYWxlHwEFBURhbnNrHwpoZGQCBg9kFgICAQ8PFggfCAUFc3YtU0UfCQUNU2V0VGVtcExvY2FsZR8BBQdTdmVuc2thHwpoZGQCBw9kFgICAQ8PFggfCAUFZXMtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQhFc3Bhw7FvbB8KaGRkAggPZBYCAgEPDxYIHwgFBWV0LUVFHwkFDVNldFRlbXBMb2NhbGUfAQUFRWVzdGkfCmhkZAIJD2QWAgIBDw8WCB8IBQVpdC1JVB8JBQ1TZXRUZW1wTG9jYWxlHwEFCEl0YWxpYW5vHwpoZGQCCg9kFgICAQ8PFggfCAUFZWwtR1IfCQUNU2V0VGVtcExvY2FsZR8BBRDOlc67zrvOt869zrnOus6sHwpoZGQCCw9kFgICAQ8PFggfCAUFbHYtTFYfCQUNU2V0VGVtcExvY2FsZR8BBQlMYXR2aWXFoXUfCmhkZAIMD2QWAgIBDw8WCB8IBQVubC1OTB8JBQ1TZXRUZW1wTG9jYWxlHwEFCk5lZGVybGFuZHMfCmhkZAIND2QWAgIBDw8WCB8IBQVjYS1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0NhdGFsw6AfCmhkZAIOD2QWAgIBDw8WCB8IBQVwbC1QTB8JBQ1TZXRUZW1wTG9jYWxlHwEFBlBvbHNraR8KaGRkAg8PZBYCAgEPDxYIHwgFBW5iLU5PHwkFDVNldFRlbXBMb2NhbGUfAQUOTm9yc2ssIEJva23DpWwfCmhkZAIQD2QWAgIBDw8WCB8IBQVrby1LUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCe2VnOq1reyWtB8KaGRkAhEPZBYCAgEPDxYIHwgFBWh1LUhVHwkFDVNldFRlbXBMb2NhbGUfAQUGTWFneWFyHwpoZGQCEg9kFgICAQ8PFggfCAUFcm8tUk8fCQUNU2V0VGVtcExvY2FsZR8BBQhSb23Dom7Egx8KaGRkAhMPZBYCAgEPDxYIHwgFBWphLUpQHwkFDVNldFRlbXBMb2NhbGUfAQUJ5pel5pys6KqeHwpoZGQClQEPFgIfAQUQJmNvcHk7IDIwMDAtMjAxM2QCAw8WAh8BBStTZXJ2ZXI6IFdFQjE3OyBCdWlsZDogV2ViLkhvdEZpeF8yMDEzMDgyMS4xZGSENbcE1oYl17RnZpLEMR/G7tH6aw==" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="pYVGjeU/Gn2hoFOZK28D2UuABBYoEtChbgjuTPwaEoZQsVXZ0ES8t7wspavb65bQi0aoD4ErRQKaM9uP/KyUveB6rDMK+K0ig4fj4sFFBgnzCpgYFnBrexAlJaYnwuxOf15rEnTj8D9FE5wMF1X6/aLrrU8Q4mICzsZJEHJDcnYlArio+rXtrm0hGUSVqqNQGo9SbHi2gsrRs2spEE/snfQL+6uMi/WNEeye4uFFty77JEYBRjbHT9u0+OS24yfdavEFJeqMolJNtVdiLW9EPSuG8NZBSdIzefq8ohJLNH7pBczHhUgncRySXC7CDGQtgnAxoJdH1lRkYLyBa8xnY/xKyjinLuQ2d6r8EXArg0tbNxvO0WLTIBheOtbDWsSh3QMEE9VZNTRAggrAzko4qEnkROIIQPVzemyLlziH7BM0EMQLhX/YP1j5UyQZsI8g+5s1VGp+726bO/yIKF6Kt+ApH3PtA5mhWBq2PJ/KPBM2CStdpTHbLGQz/4OAuYcvjT9fhERhweQPCQV6/AO1+MqTgEp59Uw3O/R3/E7h517WpS+3yWjlQoOHptUqS+Vfyy6jmxNI38TVZKzUJqv3qCSJtyesh0Ta19IX2dM9suR1XvwQRs51nbIlpYVAgCA4zCzyyUue5BUvMgR6R18In4DfkNDkGDYPkUMt9wKpeogG6RybzSIt3OZyRI8Lc7kxenA1WB646FDVoCV5j+UGrNakyHCfuEhx+0kw76GkLsh9WNaJoZ7yi9iK2QOmMrTuxpylnLw6ouiSaNHISDSTQuD+P85pHlfISRHnnxft3Vu83HNsoWvOAJjpLxJKJTxYb72GcAHN/0eak7PSG89kDM04uVcbASa8EL1n9/X3GGJ3LQTpBFUbYz2KX1YYIcxevsTtPCP5WGFjDv68Kh1iVRTHog8inEm/WPL9XldQM5N+kKJOgk8YqLdGm2KSfkxWmaoWZ93Fod44gLhx+pWXcgxPMmVpcwAi+cCDNqlM3EWWjR8pjG4ytYDX7fx8xDMwfWptNe0wZ6j51ZL6lLxLQgcCqEVVEoCqkOrSs+HUNjOkajQENRxPxASsc+wx2Uw8al2akr6qmJzE7R8Z/Irm0hEI+/0duZSTHJJYefZYiaZlO+ZbmzbaxMOCqDldu+fNzS9CpfaaITYuy7AwgGshYliYgmORINUt3bkmA548uGFMNZV1KUjQd8rDOL7JnqbPQ3NEw2xqytC8ka6lyyJlRX2lvHKCKgTQoFV6A/+hEz4O3nFkcfxDo3FN71CkMipWhfZQQjmty1oLrsLL7ncTTSSUmQPKhHQfgsGyxJPVzoe9Nunbhceg/BOVME4bwh9i8ejeKkU4+ZOCa4PLBHDlUuYdcRkZiJ17TxoT+bfnmcVpPtJfZS5deTkBaT1c5MBG0cBB6QVJ9c7qUrmYKQW28WhQJaTWX0LzIPGa3esDNlY2BwZDhZ818HNVo5p2p7res8Zps1D73vCjjQluTCL1rjy8IzyQPesaYL1Ika5vN2SMTDEFN3MSXXzly8xZQB+/OdLea3UNebMVgo399MfWnv/tuDPDlJ7+0trU5khGjaOGmk9SmNUY4DJDEYqWb78/1qYi6pkLHfox+madJGM6Et6l0DCTHGchldqvl+06FdiQ8xErU+qAswk4JiHOekMvLB5mg1rX/Eb3ZoAIvAkMUXBAoPV6yq/l2f8F5C1P1SVtncxNal0pYC/K9oYmhf8EGavajBZmxnQWv5DoAQDG/yhd04GP7M/4K+M+XWEyE44h0S4i/sSpYTdA5vA4SssoN8xAfjJE+TKMML3X4WKkHuHBNNK1bhEPe8ghBdKsqHwO13PJZtkzfGWTuWkDrCPxCFtJURQC8JhHMUVNPSTJ5LV9YyRE1B/poWTIJOqXo6B4eLkPQ2ilQrDOqfWzd/HqxQGxL+E3TuUOH2098lpMPBs00ykorZrPDBOUg8CdAtqyePOexnQCvIv10QcEIpBQTqy0lvGLE1zs4mzN6i1Uydarl3v4xA6b5H+0rTVzzGpYb7+FbUrVIM4d8HWJCEOQGQX+jo2XrRlW6NCaTPSbVMq3Ov09qg2ZWvDxc29GDo0IbgnWVFgqUTYFbTI+jR4LSDjq8HyhbuaToBZxDse6Tei5Rbc4qx8dKVDbQ9ZcLqzgR1FTZIbLfvzRk4RhT+sD4xkelHorXOTZn46m4tYagu22KgHZp6PF4o4n+IgGaMkFNU/KIYeRtbsPmgn3ka3ke3hBOb3XNqYBSb+k73413dcCHo/7pzL2mcTux64QC3xYa5Luw6sQI+Gl6uaDdDowFKlrZUk1JmLHK5nQxp+Bs3WjccX2Rr2/2mCKVSdL8ZHHESUjGRA10DUqyzZ23NVHm9aBklzFSCsJwqtcB+Rt7DHnE3UuWeueyemPPceBiYaD8rmKUAg5P57HQzN7jwfpbtF9GwLjhIWhbfhHRBa9rFqYhubXbYizjWllH+OOBDus6pwHGD6Yr6Ab05H8MWdjAH0O5cV2vGx0KT0VJh+ZXhz1XYA+M/yAY80bq6NwAXbtHznsPtLScgUUUkG0uZLMifESjo4KR4LzIAUb475R9TLjLGW/o8sDj+aiPtdv+hNTB/nZycCPyfaG38+qD7XczeHq/vdrLZ5yIIzVfYeafmtigX8uMWxvUNXQhIAzkOLB/kgojZtIGRF/H2UteDA8fWfy5d0YDB5QRC6L7F2Jku9Vhc/TfWGZBeuwXwtzk1u6z/SC2661luVRstoMCAcRyzjQYPuYf85ibC6C/I4ZTktWR7j+H86VuOGSwWZNud0lC16kdOi6s/iSRsf+VElwdfCJRaoxaUZdn3w+HYzYugCFWDYGGBze5+TONyxSsF7gtq31OrwYKYZ8uog7f+9ViFoqjl92wXmkUPf3KI0w5UYzg8jNP1m6AMchGWT6EHb2nfw/GVOPTqiwyumwSG7TZFB8+ZXuqV87GTobeHU+XRFcWqdwfy0S4fDSbEp6EkIgWPHyp4mRQRl0n6ug04PO0x28nuypsq5fPo5wdvXhatAxLPJxpRha5d/PD4HWldet0ti89m/LV9C5AEyJFcwTChZCEWCpgPzFlj6vliYag7foIiuqzn17sH+bERgr9YuARCZRC2tGPMWkJoYKDn9PnjdhS1lt9bfw/8AzeZ2+BzApeO+ubeS3ktW3pFfAjEUDsTIb6U5KN2PuynGeB7G0REA0SRhNPII2TREUcxOae7xjo8t8Xdx0HSfleXePcJvrTmZSpw5T99uguW1mRzcCxAsioeOW7v8d6Alu7zXEVlMRKN6eGf7gfsORrC0tP1p+oHsPIQxim7KCMLjW1ljOcisM26oMjvmgH8n2ECqt7OSDf24gmJhEdw833cXYlIIsLAXeVrztp3C6PsbN9OBMntx+NaiWuQnxz20kUktn+Ez1p7FOlt76RJWbrTDo0BKjRk8hOMgJmdvSyL3tP1+9jTqaHE+PqIT2+nm4jTMY9Jw65Ir0OMy7uYRq4G/RNl/oag7vShQUnfum6r8M2gyQtgC6sceSl7AL556wqV/NJ4WS949kZY5ZBFcc5bfc+1itb7wjnLbk4xXoYSUdQIT4oUwFkAS1LM0ImsjClLm1bcTQFWOCQAtlS5KE78uvp2udXC9miG5kzaCg7Kgoc3m+NJ3BD7IgZ0lCwA1S0/aSvglVakUXM1N4IPMlRzSDAPzKasCDMIJNUwsVOJdHsNs6OU55djVA/7NaPIBNlSSaj8+wv4MrtahZ77zfgPbDdsSmfdagF9R2Fj67DPrR7sIJ/t7x0Dv5DyrFt2CNeQeESxWiSb3HDCpJJ/Q7qZT3wRkuI7Kch2Rb7K8Xk42J3p/uoBU/JcgUtGBVgZ4oTZaGQDfwCrxHKLdfgSYdVF18e6z2ts9fm3KYPuiYLoeMrfI3fEDrYocUQXcJtK+TRPXgq2TGd/rwZAbl1dyN3c4P78P7hBi/pVY1L+M8xrIJfGMJ4ZzMIv6b030ElfeOLk1+FY7ru7q3GeUd5iKas7BhGFEwfuFMtU73djWvbuN7vB8MFF3hvGEJmn9ZZIAh8Q0wql26CrlVaFTS/C+dy8tBC2JU33bsX4gYN/R7RBOM/TVJXiatRIVhkr3DSQh2T1lBO+4MsZhPi7zjZ5Z+V86ojhMc0Mg0Ml/LNRJ7GTZklwHws1nwstxuB/obQTtG9ChiA1XEw/cw01sunuvS3Wz4e8XLHcGwW4qdZ1clgbWPx6HQ7WeD7mQe/BZ9AZj78PXv5r94Bk5CqOi9ZNi2MRF0AXgFMoh//48aGaBkI3uqYZkrm6Vb16HNIisiYrqkDLf+sHyLTTkvKozHRkzvRX+/maTyKkogxdZpdJCq+QVPU0nH9uCHWnZGZ949kNS2KdUsw9xbE/4YzP0dW9l/4SYF6V4s1gVJmS8oG9EqjvPTrrTDA/RxpLnpq8VHl8K/SNzxT0nI0+P0/x7Ol+M6DAByExAylxXPPvsBbz+AfbLXnEMnGH69MZrpC6KfmEVrzfO3BzsiU1a2824ATGf1E0oVQy1BiqanIqfs2VsKPOxMABMZc2+YPI2bIuGqbVj4guve3rDHzSc4oUB97vnDFhhUmIHCYKknHk3yb7EPw010RsqjjDUXPwQ4LNB1UQ/c82PYi4Sple/ETXQczlnkbxA7LpghWgD0S/+2/K5THjxiGijbt2ZKJZlfenrEyaeEyum41qGarjSqmIfYE7xTTMmFppseBVzUkCSnV47eiSiTQefN5cAN16VTlqvUtUAu7yqu7x6kfWEpKvi8h/v8WPJn0xTICk5O4VJCOTMiySWdPtT6t1/PLYW7mWK1NUzZ/Dsr0cnmUMshbypcnM9wQiSX7JCgLPKIywh9z7yNGQi+13RmWCgj/rvRnAexbCS+BR10722a3DgmxNSTctH+MfYeefb/B//SkLqeFjDXbUddOLTiiPOUFtl5ce+D4b1tGI1XfpOxHSO+UikMeVByP/LuqIbukk4W3YCLs2SbyC9r6q4RiK6zd4yfK+Ia7ZYN8HJzSHVk0XAyW8YypdYjk5sLp5yE6BsL7rv+n8Ysk43bIbWoZ0injPFzNR5y8cP+N71ZCWQ+EUR65W0y0sSgzSI/A3XjB526IH4lVeTketgPH8Qj" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="JqbbGy/sA9V2qfazjsLT7XH2gRBUrcNS7n8mgF0bc+FQ27tFw1gUMFiIQoqSiNxpuYMA764vpNQsM6JhVPKCyKp6HHlFF+EhDGzTQBzKWiZ1YtGheKiiVI7cknmWaD8f28OBPrKUGPOVIG9r3yT+k/I9KXZv7O+jCA8yUkpxJbPHyarcuFoZvJOJRnzy5CcUSXxA1LJNpzHIJNUElPAFP1Ik3sg5+qyYh2nfFCxOoArep8rGsFVS9awIdez5RxxE95PMKy9P8jbdgC/tRrqu77c3KX3ouHZACz4VrZqvHGnc4hOaAPbbZiu+UH/HoHVLqZetk/nymA4v+g8NZR7cdduniTg6rKKeaHLY8gcj2AmpPd+fNcX1FGcx9eo5X+dsCa0A4bq10TMhgLfG5FrXkdCDME4xwCJbAJHC7dWauL84ffNWH2GNwb725mD+IRdJCd7vvbW0ASCwOQiBu8x+MtUZg9HWDgF8VqsoRFUQ2pfbc+vWH5YyLzWG/kbP0Y+BDamzYMJOREb9BMa0an8PZaO+/BaE4hLLKwSEdPZuNeT0Bf3/RmzZ6QFqnwVvRkzMA2HF181X3Kli/xh49Pdj2SNlila8jbSuSthHwEk46ZV6cYDzkLNK3xZudm9TLl66RFps38ZaiTZ+jzAYQKUrGNRGsKcY3uSXBXARqjXbRPBU60hJdBh4fz08SfmEeAZMk57HgPwPIHU9gXWisNG5aJD+yNzN+G2seUjdkQvqSt/iiyNSyDmKDwXtNVtBEWSxe6LNzaq5NuWYvRwdns7yDQlHMrmucpi6VC684qUkrL6TmvP/2jz8IdU01Vzs8D/bJjTCmU/smIAPCR1tRrhuwEGpYQPfAxSTsW5xmNsjQwTIGDRq3lZOf/BMwSU2ag7wz4yqz/NN42vyLGr2oNrlgJry2L9MlTEnigJSsaUGydos5VEjluWTzSXyA4IUTV006E4onJXe9BZClPGUzRDTrquyF9rKdRBVU1PZGdVDA/4zOEGhvxhd8lRCfkCWcKSXdom68mEAYyPFsBi/DcDUCfxgGWVU/XPaUowa1pLHd3GXFsky1iwyGinYPslbSnZy3Buim5bVBVQZpb3G4cvlK/b9o2h/gWaiahqMx+6FOlnMiQYyC7Lxch5ymjR2STRYNEu8eNuJBsKSXL5bhwoU36FBA2doiRVjvgoN4kdZMDCcleDAHtwgiNCB67iwjar5LZ1sUlgsLzTGQ+cqSTRG3/BW8Rrj8AXDfTTuEtNpuau5LKFIt4B2xrIgz4+DrPuWG+6oJffFwBeFoFzbscQav9ozZXMUoab8tTjPNYOf0j1wWrZWhKT7cDpmnkcAbBfEvON2O/sawOCnBSRpavyzjNO8SNT0srthyKOwfRl7yZCU13rtgsLKCg6uDS7eqSZunz3VG+c2XKoVR5VYKfxEZTGHKB9doXpRh0A/MBaPsgONjL/nx+sG3WKG9SaCP4WbSHOAj2yGT2BZLW1p0hsP8cmlXThU1GHOXd/352AsIn38PzFf3ua8Wu6ADpUvnadumTuBFSxHedjwe9bNfeiAvuVpjqgBE+duRe9OYBfoiepuZ0zoyyGREgC8+2lpetJCvoF51GWFsmdcw1C4WUzl7S4poMkbV9wytnzkVr1Ze4huBXkQHTcnZuapqkl568VO5cyIwp0tnkGz2+7tA8BoG26Y03paMHkjXYBj2vpiL1TluzjS+O6PW1r9qtsaZJ67/Q0O5+5bhxcg3jT4czOeg0qMu0CNCcHNt5JEeaQ/hG0qTGpr+3kmPO7oERR0RAShTShM29tqi6/P2EZWA9BYBYohQcgpagOcEBMccUzq6FMo8g+Wu2STscKdUpjR/vhePWc7D96kHlyb3CxH3WrXX69ilVGMkvB1OdTGDUt23UxJ6Mv61v23lNJp+LfHciJuqRJ/FCcgcWijrvq3/GI4RIDHRuygKOd44WVCz58GcSNSzEKljVtaQdzQ0p000dkrCanVpHd/iBpXj2zURzNJT0C8EVpWWfw78MHHKItmKERo7LvOeeogeG4hZB5GJkeorkA2yJakt5uf0sdyYfNjdxahA8DGpMnPsAMjLmc+7X9myOXWDSD6xNzfbM4wOV7sqCP9+mE8SEnHPUA1jFoBWuj5E/OLfk96AJ6GT9Js3SefL4PpyNkPgt9G+1geSj2/SdrnIdvIR4yswCETtkustiK0C5WcX3k6RRZcHp5yJLK9AeySwb3WS7G+DVqYon42XCt5kgzfWHFB0cO7EhQ7DzzbsUrpAP6xM/aZhbM7MY0F9fmxUAjB/Ll0NvHWYuXFGUTKiLfyXgSKMamiQf0QmpGXmJL5Ek6Jq+ZZ9rVkjcKu9RUxapiARXMqGIMAahKdvgy9YHqXVfrxybgIIgVL4HR6X2dqGoSCh894BcJ7Dn3c3Vuzs/WDz8gJ+/p9umvMm60HKgyHLf9Csd8GnHgTlFjxmGASwanmUZztpFmSSeUF3J2mZXbbrSKWIuytyHwBdV97DXOGIcKuN//tKU5KschCHaYDAKkjH/r/Xj0k5QBnIOpH+ikO6UHTin5C4uayu6BILO12/YmMluYUl2x0ArzC6j1UWUC2vemtuWv9v3jqwMssfLvHM/LwPe68zoVTMPYtsdpJoxdJLnbIQ47BmwnWrh7LtfQKJqI5FuV7L90bMwAnJIvv9ij0TXBjkQDZrV8EzunTEa3++B89jkNnRS/6iE2UhyuK+YJ6kvMXPzuLzby/CDgJlRt0gk8BZkt4fo+6oaRr3CVVkBNyRewlntU7t7x/nirwudoUyvVlS4lrauXhV1GbhTYKUjaKcKkwb3P3qyL7p/BJKf6YMwqPPIdz/YSVKWFsiwZt8lS6ytDAI496Luw+yPyF88gOnG6sWVcNUjCsqthN3WYZILZxsdeBP4MHLEI/UXVad74vrcxj1lUHxzvXvLRp3dHuZGQQxTNITq7ai8ZY51RjT8cZ6ldbrKQHyNmMHN8BkGrp1ErO0uYiFhfL+fCM2sI5afGAPVZw3HSBSAPqTRz9M4bvEI+xly0S3OV6gmx5Llmq6rKJLsNi8/OnOUmJeTC4xX1T9dKVlFCKspNhi2FaOBnGcDw7ju0loE8sSctG9n+wK1Q/4KK8DZhlKoQfmCfhBe8VRDHWwlYV1YdoUK1i2uRItTSgQFTZ4aVY4YJDGaAGJ51dLyVO/OHpG7Xm1cJCwa4cTj13YCZRbKUK/aEsSTwDktsDWS0VvtK9Q14PjrvSj1EsyWjI8zWRgmXDVtLDZyMwxoiQden3gn7j1R/MyslA4zvZVPgeLeEGxoyv88dKQwdfcFvxQTKIrzqdcEQ6YZ54GZvek/k6cK1VwgzWQG6d3JhkTqDRAASuxmRKK14t5EoIsRkqb7/5KWMRX136BW01A5+2UlHpVybCiq9lTrelIhFRYe1EoBw3QivO6H3jtjDdjl228/6hnPyK+w01xn9lo5ULe4f85ZbIVJ4gxMEH/KIrTkv+/rFwFxsieSoXOn50t1VMUA2FCje2JriDv0Tz+3y75G7p3SFoHoj6BVlhPHW/GGATcUHceEDQWmCZ9hQboSpH8BM7+CPxR+MKpiZL/K6D70BsQ3HwEBniiWCNyjHDd+J+IUrmWiJZITvdOaGtZW2fCnwuGjTOZdN99jxEbwpvo6Aiag5uC5OyDNakY3+DtoTxIQuqXRnVVuWEXSN+I7L0kUa430oDK1Gou8S5bbOp/kOJJlAldpRv9BOUguL02a4jDemx3VJvmk7zsHkgnXDf/vwImi8D+DCDKK9pU2CAjv4gdUHLYa9/S+UYjTMvzcjPjJ7rSRtDRc1W+7HbncUYMBYeZaioSA3JuTJTNLeBsLqreZTx5WSE8amX0EaMgPU6S5VbMS+ckTUKNkmPtMpS4VpDoaZRo4Gq4fUqf6GFeKf4N+SHHC7r8r9+VXso/ukuvj9EjUm9D0XV3ztkk+QLo74Xc7bKgcOZLFRdBgp57F/SISc77uyyWZMq69FOPbdDxarFEyeQwzEST/ePXElxl65Awh8JQyCiIkDGf+cnBqOwYN8oeIduHmuUTYcojVtWAyN0wqirbhzTQPFBEUbuDT11pw+7KIenunb+fLWdjMY8XSbt7QC6T1gllkpVOnvsjSMHAPCblkJUOGlLNfnlYrNnPRN07nI1wXnlCdOJEEvwqkJjN8+gLdaa8TSmPq3JSL+Ludc9rXb1lPdtpxqitMGDFg92tjiBx6zDhI5hMlWKxJgSdgD4/qlzAMeOugkyPitwHB6EN+MmVCUlXdqYL1IsiBCHdgIRA/FsarNDnatCJbDdWJ8ohz2Vehh6itD4DZBxq2VHGFeFgPUjOeihLObik2/G2xZzSL7sxJ2AUg4UepPFs8l0V63i+4KFP+9j2tj/26kokaexA7RlIR9boNeRAqijhr5SgdlU/PLVPP25Vjop/yMAlHI6KaYIVDWwCdl9JIQqgX2aoe4rEyBvGulqmdBtKhJNSX4t/vTl8GY0xeR74iSEXPF+9bogR5QuORBXOzL8dqV7j94tJTc7IAx5A0+7oSl4Gr34g8f2LF9aGCf3igKqpq9Le9iQqi+PhwgwERu1TMkI50lEmixnqIeOhGzQtxOd7HnzVtppmoGrAKVVAu4dQ74/7tGFReeseNtIO1WWH+ynnUAk8SUDZE5Ewlp3oJTKpa9BWBBVmiJAhokxYROWYWBTa3t16QTfQwoR+kNuElQCflE7nf10yKKj7cPIHJsy6ZwhMhstcHI0VxT+a3laQQy9NQ5a5+Zp9QM5w3CKN9feA/hlbjsZU7H0dN+EIxc45oXD4q7zUtSBWydsw7RrC8Wso3e2ctco83Md0o/GzlEP5bAjERjzRT7ciKE9p/vLrFQIlwoEGZhB+TfjF8I/BfnotHEdqa/chbGpSj5ES67Lap1coDBoLXetvtqE1CfJogm1NyMHlxG0/ddBPhDfc/JZf/kUAGY0xyYbZ/VQZZ9fE/uoHnHHeGiOHXnjrzyUOkCPr0+YrhALFXDcdEsFiNvTtCFQYeiB+xwspERg01ivCkJ4uVAMZEfakpXqvfie61ttebWP2ZrRhpp/GswJ/gd8ATpvLmYg/4eIRv3g61h2d+tg7sj52V4Z3ldADGD3z//G" />
+<input type="hidden" name="__VIEWSTATE2" id="__VIEWSTATE2" value="ANLVndue4UjH+JdswTjGYWgNaxtJdpooPaYTWAmPcPRlbOfrBO1FOrzGzPI3aE4VELbIYUt4xgEPNb1iw16k7A3kLPCCEX6H4zfGJ0WmHt2eVaXuwh0inoWz8tY0HIWmwMcpWyudJl2ZLMTu6AkOliXdnlzsoGaHPUYu58jZk8rTyAxb4UWMxVv+nkdxrjVlQobDdwLtMhmvTV029N5byolkog4qabq/ELXaAk12nlwHvQKebgK6syRJMl5tV+xu+7ZGacpzb09nTbrH7hWU7VCvR+MtuuErvXYY0W4P+OC5idv4SXAk3wGcPgBj2payFQocDgyqajxi9AMFRm53Ve0K/gmrizwBLJGe51Pvh78frY48pKYH7MC4KZUGRD39g1+zKPrQLJOK3s/9oHssxTds/xc47zBupUNo/xckVlZ/7kdp6BOGG79bWmmv15FLSFrwfIrK5ch5ia36sbjR2JiWMB8UtW7dIPE3Z/cvkAGFsjzL/iVHdwCEk+F4OGjxbErRRcGzHPrKGAu8aDcUIV+CawrWmJQhzs7oijWY7Kqn8XirEI6CI481/6DBZW9YbEtf9mXAf0tL6/hmKBsa4TVEKXDifeJnanAMWtNIrkD5HZ9l8dpZaHO1qPbWyIcRpPyB8vkhpAIRVYpjX9vKwc0rD6oBPx9B2preWH9CivfY+R7+wWKYgeaM2Xo38wWT1SDzr1B/NNCK1yTgxguqAZ9/B1nTqmjXWTDtpOIFUaIK67BBB6reSVR1RS8AvFhXZNHClz5RNAPDJZQEhiM4FdE8qltbFSMEDftdOKr+za+TT/YLFiLgbT2hCOb6FWxMIW4QTz4bcTdUq0LQo8nnivXhSEdF+bM5gV/Bbs0HL00uYjyQsOutJKYUvUjrwEZigamBaDHQWHwgsl63j3RgN4rJEOwZlzjEm/ZxQ26nczBhd7sBT2u21+JsvShs0rvB0dZB6nvGp4CUVgU6LCNCKtLdC001S/7AbcbWntWgYxFv//hG+LFjjtrAwPlI2F5PdDjQ6BxupaHJbMDvPl8U8tL/BBghm/rDbyJLh1SbTmPyPDptgZVWASH0FkKovhYn+Ucb59m/Qy6AI+WeJjUPi+Mmg2G32QiY0ubWEzhnRhwYtoio0V6HyO5BDql3RDH/RHLGqWGJfbdanJpbtxX/S2ofsBM4UDwsQvft1kGThs3FBeV7OpHepwSyltyinQPv40NBsYjUxrvANnXHNOEvnfWup9r6BC0lsrI/qskGiZ1hjFImLEHMnvCGl3iFVe/hM9x5Bn1XRjbA6mlg9ZIGvtzVfxHvPIjEfzedn2T+YdXjr71U2z+ygV0K1Zd+Fwxp4M/ZsrOSWE9WV0XQc5mDNq5RM/Dv7FmdMsUZTkLpt6fu9F0qob63BP+FUhekJVQZPYBzA0v0zTbiJkyRHZtWprKvUnjQqfyrSOvdY0Oy/ngWa+WqTv0RMXP3U1T0MJ93ONPQe9SxXnEVLmaAJgbN0LtYM3/YEVKzofW0cnBegpcgyfvRkLkaaTotIoC6b7vRtYLt8L825fm5rDDpzn3OuwZThkrbDPSU3UhYVwjnggWv2hI/DUlT3Afb+b/M+3AruR2zofyZGN6fSuSoUIO2nQc4QwSk+7/aH0eWEfYyNCmlzZOuJBP5sPmJhL5CMvoRHx69JatLY0wk6QDAs9v5K0UQF1du0cQz+bJArTpOgxbOVs5aTTOTTPklZO6XISKKY69JM7LcaBtKxzU8tpNlpeU52MucifftvQ5J5wfukGS45N9Iv5j2fTUtSfOCStWInlsuGGLDEEgK3wpjIlqbr8hrzew5TMQEqzvNqLUOspCMNAYzx2N09S0I2LBHz4tEsMXPxbi8TWz8x4AjU8Qo3KapCWmQTb+V/jpeAuk7i9ZA4xIncx4lu1T89/p4KeQQIq7hNuDlaXmXtvBiH+6bwzdYEc9gGtKngZNQfQkcu5ipNGYVlAnVmumy+0qEOGG/Wla03rL4oOjRS1VekH7SB/KD5zuIYGK/VPOPtOtVwimESJ8HpyhSK2BKHKg9rpxAPoM3tk4QMPGR31NWyyq70a6sNi2WZ5775vR8sGDpxPs37d3WvH8nb7n1zcdvotvAxhr0bl9Upct/5MjeEEKi3RLEQYvF6XHUm5qLt2V43hrmT+68+uFyXRYN5hU0k3aiZXg7+OaxYC5hsFwkfFiTwgPT96lQ08Qd3YTJ0N9LRgWwWomUquszmii/Bu2n7bLZF2cl3g==" />
</div>
<script type="text/javascript">
@@ -92,497 +107,397 @@ function __doPostBack(eventTarget, eventArgument) { </script>
-<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634981136287450696" type="text/javascript"></script>
+<script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZETFLbdR8wwRMdub1eDU5ILCHE7OhotblLUuaNwx3HQ7rYen0g2&t=635418606520000000" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=ffffffff940d030f" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=ffffffff940d030f" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=VZKNgu1isPaAINPNmSDkniHRmEiR365Y3EPnMj7AXSlsW-OjQIYc7VPoltqjVULZ1g8K9CNDrBJuNvUVOZhFqH3NS7yTvcU3NnCeS_FcC9dLDDQ8Q9UH7PW6s-B2gF04VAooHH3Ji69sDY7LPmffv0PShiGc1206s_RLAIzuI952BGa9reXAmYClCuFJH4FjsvPZoM7oG82eR9HPyOS28x0KmiQ1" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=H0ET7B4U8EJwmcAbxjSGxSsqhUYAPJWkcrAuejTBaZ7N1SX_jc3D8QuNKUPa0lO4X3QHb4S3pibvaKNYs1ChjXro9ahCfiZGcYIQu6Ypce_q7YOm_PkXbcyD93f6aDlH4D9eFkkuLiE9Ax4WQgrrygMqipqtLqR7mio-gp6w-ttXgLxtrsFRt-pUjltSCvHgWUwBtVr9wTSTuzeTLswFqWhBmRPpN7g52pLMsR4cwsSOiAKUeb6dRJ_DZWWUA7Gz0XyQM93WLdA3NKoaC8qUufQM3ZOa5RAudzueB87VFLfeuhZXxK1-AsHyrJkHMiOGwGZjN55yCPtP1BEwdRcWpCJwU7Y_efv4APmLdYZJuvt4AxhKqZdv9FBT2n8FSDrgUdJXxmOVf_5r2_lt_khWegXBwRoygGjD3nKfQf8Q-zpyIsJZZDzQ8Td_2c9eDB4Zy1LRk5dNsNZy6hAaWo_Uq50DOnrNf0LY0qwB1ZAd9b-kZLlEUQjaCXSSBeCccOLbgDalKaxQ15-fEh-R_Lqgt1720fRQyzlevhgNz5vknnm2hF_vHLKlKAoJWuuSIFEiIgEz-JeplpCgAtzjjo0mJ2Zdl9v_fAQxwE4XgBXmUTaiSmoT6TxPHJPr-3BmMQSZs2qBNbYrFu53gs5JbsKPA0pdzyHLlfP2bYUDBdjB1oCqq5qW0" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=uHIkleVeDJf4xS50Krz-yEJRbXY2x1dOBEdM7W-QkNpgaumdwaefPzMErSeG_W29-lHX6vl5G7uDafHaYWCx8Z9aLlo8tZwVtV42ISp6LhT6LbxuVUWMo5GyApWAyPOqkSkf1vCyntgT-PmPv-C6FWxsbWo1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=Jw6tUGWnA15YEa3ai3FadDbNvwkajNGIHz7aGm4w_MLRMuZ5hwlk3bfOsTs3E4cZZ4ktnTFE_MzciTx4exD15JXabrPKGazf6xj6fW1A8vXJoc3OCqf4cg_BDlVl8fQEsQiziDh4kHnJRWZEQotwuLoezlg1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=LsSN37T_JTo8WmXc7IWe9h7QNKB5hH17UtyHRfQt428U3aulvj53CANg-qZVzIBuh0jojGRwyA5u6DVnEet85JW-JpWduEGLE0VE-2wGHR4yu7MNj7XtsTLWd21Jk8RZENZmygJcHOHGMS1oisYKTWQSIQA1" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=VUtFLQIK94pF36sSxa5M5Q4KyVgkk4aq_Lj3yxNWv9FE_GBcdEQWlyUYzpoPTO27D4G7EbYHTqxoW35XPdin3tebmTxp-wSfJzzK8-nJzs2HapzFx4fuNPR6OjDBQmtyWLMl9s_v9cfV2Mm7C3dG-PYITU2UMwNSjAESeyXFqfw8frZJE2LykLAMOmhcIMdVDEZ3towfhsTqOSZWPCdiMeHylJ16anMqLsL7z0oT5vyUbvIiPYHpYKrAEJIDFxritjPVOv9orjoRf-8NlzG0PwzvCPCUNUOn0q725aaI6lCODxhDBiPw-ciHHQzmbbGdaID-mnjIV9nX6-dgUyOpCAzwZXAoBQPQ6TU3GjtYmetglM7I31meDWRS7sDj-e3m--4pB0SzCNbw9t_ZQ6DjARVQyTvBJksCHM-RcfVHoBtuq9rOTWynsJGmm_Lg2JD7o-KVYJOAuPGcUEcNWxswz-cLWquZQ3_vABHJxAaFz-lnYYwzEyEWn9I2tPIwXjHtZVAB3g0G-dsEEFKNFYXpU1N0r25KNq4NEKXKQg1QI99Bxq6sUV0UkKPNGk0f24VH7_RXyG7L9I3rXDfYaVq1X300crsUh2Cn0-mUkdpiqhtb63KB_jWzXr9HEzeR_socdD-U_PhMKdYigWqerk55eRcMsVPuiRN1yBkFE3GQiZawEqjI0" type="text/javascript"></script>
<script src="../seek/js/cachedetails.js" type="text/javascript"></script>
<script src="../js/latlng.js" type="text/javascript"></script>
- <script type="text/javascript">
+<div>
+
+ <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="C05D5804" />
+</div>
+ <script type="text/javascript">
//<![CDATA[
Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
//]]>
</script>
- <div id="Top" class="SkipLinks">
- <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
- <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
- </div>
- <!--[if lte IE 7]>
- <div class="WarningMessage PhaseOut">
- <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
- </div>
- <![endif]-->
-
-
- <div class="PrintOnly">
- <p>
- <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
- </p>
- <hr />
- </div>
- <header id="ctl00_siteHeader">
- <div class="container">
- <h1 class="Logo span-16">
- <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
- <img src="/images/tlnMasters/geocaching-logo.png" alt="Geocaching" height="43" width="301" />
- </a>
- </h1>
- <div class="ProfileWidget span-8 last">
-
- <div id="ctl00_divSignedIn">
- <p class="Avatar NoBottomSpacing">
- <a id="ctl00_hlHeaderAvatar" accesskey="p" title="Your Profile" href="../my/"><img title="Your Profile" src="http://img.geocaching.com/user/avatar/e8a97a05-a051-4da9-bc93-6a830b866aff.jpg" alt="" style="border-width:0px;" /></a>
- </p>
- <p class="SignedInText">
- <strong>
- Hello, <a href="/my/default.aspx" title="View Profile for JoSaMaJa" class="SignedInProfileLink">JoSaMaJa</a></strong> (<a id="ctl00_hlSignOut" accesskey="s" title="Sign Out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC2CJPF%26title%3dkinderwald-kic%26Submit6%3dGo">Sign Out</a>)<br />
- <span id="ctl00_litPMLevel">Premium Member</span>
-
- <strong style="display: block">
- 484 Caches Found</strong>
-
- </p>
- </div>
- </div>
- </div>
- </header>
- <nav id="Navigation">
- <div class="container">
- <ul class="Menu">
- <li>
- <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li>
- <li>
- <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Geocaching in 2 Minutes</a></li>
- </ul>
- </li>
-
- <li id="ctl00_liNavProfile">
- <a id="ctl00_hlNavProfile" accesskey="2" title="Your Profile" href="../my/">Your Profile ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavQuickView" accesskey="p" title="Quick View" href="../my/">Quick View</a></li>
- <li>
- <a id="ctl00_hlSubNavLists" accesskey="q" title="Lists" href="../my/lists.aspx">Lists</a></li>
- <li class="ExtraText">
- <a id="ctl00_hlSubNavGeocaches" accesskey="m" title="Geocaches" class="NoRightPadding" href="../my/geocaches.aspx">Geocaches</a>
- (<a id="ctl00_hlSubNavGeocachesYours" accesskey="y" title="Your Geocaches" class="NoSidePadding" href="../my/owned.aspx">Yours</a>)</li>
- <li class="ExtraText">
- <a id="ctl00_hlSubNavProfileTrackables" title="Trackables" class="NoRightPadding" href="../my/travelbugs.aspx">Trackables</a>
- (<a id="ctl00_hlSubNavTrackablesYours" accesskey="8" title="Your Trackables" class="NoSidePadding" href="../track/search.aspx?o=1&uid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">Yours</a>)</li>
- <li>
- <a id="ctl00_hlSubNavPocketQueries" accesskey="9" title="Pocket Queries" href="../pocket/">Pocket Queries</a></li>
- <li>
- <a id="ctl00_hlSubNavFieldNotes" accesskey="0" title="Field Notes" href="../my/fieldnotes.aspx">Field Notes</a></li>
- <li>
- <a id="ctl00_hlSubNavAccount" accesskey="a" title="Account Details" href="../account/">Account Details</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="../seek/">Play ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="../seek/">Hide & Seek a Cache</a></li>
- <li>
- <a id="ctl00_hlSubNavLogCache" title="Log a Cache" href="../my/recentlyviewedcaches.aspx">Log a Cache</a></li>
- <li>
- <a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li>
- <li>
- <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="../track/">Find Trackables</a></li>
- <li>
- <a id="ctl00_hlSubNavGeoTours" title="GeoTours" href="../adventures/geotours">GeoTours</a>
- </li>
- <li>
- <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a>
- <ul class="SubMenu">
-
- <li>
- <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a>
- </li>
-
- <li>
- <a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li>
- <li>
- <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li>
- <li>
- <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
- <li>
- <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
- <li>
- <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop Geocaching</a></li>
- <li>
- <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
- <li>
- <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li>
- <li>
- <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li>
- <li>
- <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li>
- <li>
- <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li>
- <li>
- <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li>
- <li>
- <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li>
- <li>
- <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/geocaching">Follow Us ▼</a>
- <ul class="SubMenu NavSocialMedia">
- <li>
- <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/geocaching">Facebook</a></li>
- <li>
- <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li>
- <li>
- <a id="ctl00_hlSubNavInstagram" title="Instagram" class="SubNavInstagram" href="http://instagram.com/gogeocaching">Instagram</a></li>
- <li>
- <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li>
- </ul>
- </li>
- </ul>
- <div class="LanguageSelector">
-
-
-<div class="LocaleText">
-
- <strong>Choose Your Language:</strong>
-
-</div>
-<div class="LocaleList">
-
- <div class="selected-language">
-
- <a href="#">English▼</a>
-
- </div>
- <ul class="language-list">
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Latviešu</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, Bokmål</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li>
-
- </ul>
-
-</div>
-<script type="text/javascript">
-
- jQuery(document).ready(function () {
- jQuery(".selected-language a").click(function (e) {
- e.preventDefault();
- var $loc = jQuery(this).parent().next();
- jQuery($loc).show().position({
- of: $loc.parent(),
- my: "left top",
- at: "left bottom",
- offset: "0 0",
- collision: "fit fit"
- });
- jQuery(this).addClass("Expanded");
- jQuery(document).click(function () {
- jQuery(".language-list").fadeOut("fast");
- jQuery(".selected-language a").removeClass("Expanded");
- });
- return false;
- });
- });
-</script>
- </div>
+ <div id="Top" class="SkipLinks">
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
</div>
- </nav>
- <section id="Content">
+ <!--[if lte IE 8]>
+ <div class="WarningMessage PhaseOut">
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+ </div>
+ <![endif]-->
- <div class="container">
- <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
- <p>
- <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
- </p>
-
- </div>
- <div id="ctl00_divContentMain" class="span-24 last">
-
-
-
- <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
-
- <p>
- <a href="#" class="CoordInfoLink">
- <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC2CJPF</span>
- <span class="arrow">▼</span> </a>
- </p>
-
-</div>
-<div id="dlgClipboard">
- <input type="text" class="TextFormat" />
- <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close">
- x</a>
-</div>
-<script type="text/javascript">
- $("a.CoordInfoLink").click(function (e) {
- e.preventDefault();
-
- $("#dlgClipboard")
- .show()
- .position({
- of: $("a.CoordInfoLink"),
- my: "right top",
- at: "right bottom",
- offset: "0 5"
- })
- .find("input")
- .val('http://coord.info/' + $('.CoordInfoCode').text())
- .focus()
- .select();
-
- $(document).mouseup(function (e) {
- if ($(e.target).parent("div#dlgClipboard").length == 0) {
- $(this).unbind(e);
- $("div#dlgClipboard").hide();
- }
- });
-
- return false;
- });
-
-
-</script>
-
- <div class="span-17">
- <div class="span-17 last BottomSpacing" id="cacheDetails">
- <p class="cacheImage">
- <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/3.gif" alt="Multi-cache" title="Multi-cache" /></a>
- </p>
-
- <h2 class="NoBottomSpacing">
- <span id="ctl00_ContentBody_CacheName">Kinderwald KiC</span>
- </h2>
- <div class="minorCacheDetails Clear">
- <div id="ctl00_ContentBody_mcd1">
- A cache by <a href="http://www.geocaching.com/profile/?guid=9a28b2fb-bce9-481f-87bc-7c5f4bafe723&wid=73246a5a-ebb9-4d4f-8db9-a951036f5376&ds=2">Tom03</a>
- </div>
- <div id="ctl00_ContentBody_mcd2">
- Hidden
- :
- 2010-07-31
-
- </div>
- <div>
-
- </div>
- </div>
- </div>
- <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-6 BottomSpacing">
-
- <dl>
- <dt>
- Difficulty:</dt>
- <dd>
- <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars2_5.gif" alt="2.5 out of 5" /></span>
- </dd>
- </dl>
- <dl>
- <dt>
- Terrain:</dt>
- <dd>
- <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars2.gif" alt="2 out of 5" /></span>
- </dd>
- </dl>
-
- </div>
- <div id="ctl00_ContentBody_size" class="CacheSize span-5">
-
- <p class="AlignCenter">
- Size: <span class="minorCacheDetails"><img src="/images/icons/container/small.gif" alt="Size: small" title="Size: small" /> <small>(small)</small></span>
+ <div class="PrintOnly">
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
</p>
-
+ <hr />
</div>
- <div class="span-6 right last">
-
-
- <div class="favorite right">
- <a id="uxFavContainerLink" href="javascript:void(0);">
- <div class="favorite-container"><!-- TODO! -->
- <span class="favorite-value">
- 22
- </span>
- Favorites
- </div>
+ <header id="ctl00_siteHeader">
+ <div class="container">
+ <h1 class="Logo">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
</a>
- <div class="favorite-dropdown">
-
- <ul>
- <li>
- <img id="imgFavoriteScore" src="/images/loading3.gif" width="20" height="20" alt="Loading" title="Loading"><span id="uxFavoriteScore"> </span>
- </li>
- <li>
- <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="/seek/cache_favorited.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View Who Favorited this Cache</a>
+ </h1>
+ <div class="ProfileWidget">
+
+ <div id="ctl00_divSignedIn">
+ <ul class="logged-in-user">
+ <li class="li-user">
+ <a class="SignedInProfileLink" href="/my/default.aspx" title="View Your Profile">
+ <span class="avatar">
+ <img id="ctl00_hlHeaderAvatar" src="https://img.geocaching.com/avatar/642d2771-424e-4ee6-beb6-efecde3406fc.jpg" style="border-width:0px;" />
+ </span>
+ <span class="li-user-info">
+ <span>Bananeweizen</span>
+ <span class="cache-count">743 Finds</span>
+ </span>
+ </a>
+ <button type="button" class="li-user-toggle">
+ <svg width="12px" height="7px" viewBox="0 0 12 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g class="arrow" transform="translate(-1277.000000, -25.000000)" stroke="#FFFFFF" fill="#FFFFFF">
+ <path d="M1280.43401,23.3387013 C1280.20315,23.5702719 1280.20315,23.945803 1280.43401,24.1775793 L1284.82138,28.5825631 L1280.43401,32.9873411 C1280.20315,33.2191175 1280.20315,33.5944429 1280.43401,33.8262192 C1280.54934,33.9420045 1280.70072,34 1280.8519,34 C1281.00307,34 1281.15425,33.9422102 1281.26978,33.8262192 L1286.07462,29.0018993 C1286.30548,28.7701229 1286.30548,28.3947975 1286.07462,28.1630212 L1281.26958,23.3387013 C1281.03872,23.106925 1280.66487,23.106925 1280.43401,23.3387013 Z" id="Dropdown-arrow" sketch:type="MSShapeGroup" transform="translate(1283.254319, 28.582435) scale(1, -1) rotate(-90.000000) translate(-1283.254319, -28.582435) "></path>
+ </g>
+ </g>
+ </svg>
+ </button>
+ <ul>
+ <li class="li-settings">
+ <a title="Edit Account Settings" class="icon-settings" href="/account/settings">Settings</a>
+ </li>
+ <li class="li-signout">
+ <a id="ctl00_hlSignOut" accesskey="s" class="sign-out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC2CJPF%26title%3dkinderwald-kic">Sign Out</a>
+ </li>
+ </ul>
+ </li>
+ <li class="li-messagecenterheaderwidget li-messages" id="messagecenterheaderwidget">
+ <a class="message-center-icon" href="/account/messagecenter">
+ <span class="msg-center-link-text">Messages</span>
+ </a>
</li>
- <li>
- <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a>
+ <li class="li-upgrade">
+
+
</li>
</ul>
</div>
</div>
-
-
- </div>
-
- <p class="Clear">
-
- <a id="ctl00_ContentBody_uxCacheUrl" title="Related Web Page" href="http://www.kinderwald.de/">Related Web Page</a>
- </p>
-
-
-
- <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable">
- <div class="LocationData FloatContainer">
- <div class="span-9">
- <p class="NoBottomSpacing">
- <a href="#" class="edit-cache-coordinates" id="uxLatLonLink" title="Correct these coordinates">
- <strong>
- <span id="uxLatLon">N 52° 25.504 E 009° 39.852</span></strong>
- </a>
- <br />
- <span id="ctl00_ContentBody_LocationSubPanel">
- UTM: 32U E 545164 N 5808524<br />
- </span>
- <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="/wpt/?lat=52.425067&lon=9.6642&detail=1" target="_blank">Other Conversions</a>
- </p>
- </div>
- <div class="span-7 last AlignRight">
- <span id="ctl00_ContentBody_Location">In Niedersachsen, Germany</span><br />
- <span id="lblDistFromHome"><img src="/images/icons/compass/N.gif" alt="N" style="vertical-align:text-bottom" /> N 23.5 km from your home location</span>
- </div>
- </div>
- <div class="DownloadLinks">
- <dl id="Print">
- <dt class="label">
- <span id="ctl00_ContentBody_uxPrintHeader">Print</span>:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376" target="_blank">No Logs</a>
- <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&lc=5" target="_blank">5 Logs</a>
- <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&lc=10" target="_blank">10 Logs</a>
- <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=52.21625,9.714483 (Home Location)&daddr=52.425067,9.6642(Kinderwald+KiC)" target="_blank">Driving Directions</a>
- </dd>
- </dl>
- <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;">
- <dt>
- PDF:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a>
- <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a>
- <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a>
- </dd>
- </dl>
- <dl id="Download">
- <dt class="label">
- <span id="ctl00_ContentBody_uxDownloadLabel">Download</span>:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="/software/default.aspx">Read about waypoint downloads</a>
- </dd>
- <dt></dt>
- <dd>
- <input type="submit" name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" /><input type="submit" name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" /><input type="submit" name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('73246a5a-ebb9-4d4f-8db9-a951036f5376');return false;" id="ctl00_ContentBody_btnSendToGPS" /><input type="submit" name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC2CJPF');return false;" id="ctl00_ContentBody_btnSendToPhone" />
- </dd>
- </dl>
- </div>
- </div>
-
- <div class="Note Disclaimer">
- <strong>
- Please note
- </strong>
- Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>.
</div>
-
-
- <div class="Note PersonalCacheNote">
- <strong>
- Personal Cache Note
- </strong>
- <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" />
- <span id="cache_note">
-
- </span>
+ </header>
+ <nav id="Navigation">
+ <div class="container">
+ <a href="../" id="ctl00_A1" class="Logo" title="Geocaching" accesskey="h">
+ <img src="/images/tlnMasters/logo-geocaching@2x.png" alt="Geocaching" width="195" />
+ </a>
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" class="Dropdown" href="../guide/">Learn</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Videos</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="2" class="Dropdown" href="../play/search/">Play</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavFind" accesskey="d" href="../play/search/">Find a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" href="../play/hide/">Hide a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavMap" accesskey="/" href="../map/">View Geocache Map</a></li>
+ <li id="ctl00_liSubNavLogCache">
+ <a id="ctl00_hlSubNavLogCache" href="../my/recentlyviewedcaches.aspx">Log a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" href="../track/">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeoTours" href="../play/geotours">GeoTours</a>
+ </li>
+ <li id="ctl00_liSubNavPocketQueries">
+ <a id="ctl00_hlSubNavPocketQueries" accesskey="9" href="../pocket/">Pocket Queries</a></li>
+ <li id="ctl00_liSubNavFieldNotes">
+ <a id="ctl00_hlSubNavFieldNotes" accesskey="0" href="../my/fieldnotes.aspx">Field Notes</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="3" class="Dropdown" href="../forums/">Community</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" href="../account/referafriend">Refer a Friend</a>
+ </li>
+
+ <li>
+ <a id="ctl00_hlSubNavVolunteers" accesskey="+" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" class="Dropdown" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">USA Shop</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlBecomePremium" href="https://payments.geocaching.com/?upgrade=true">Become a Premium Member</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
</div>
-
- <h3 class="CacheDescriptionHeader">Geocache Description:</h3>
- <div class="UserSuppliedContent">
+ </nav>
+ <section id="Content">
+ <div class="container">
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+ <!--<p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
+ </p>-->
+
+ </div>
+ <div id="ctl00_divContentMain" class="span-24 last">
+ + + + <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
+ + <p> + <a href="#" class="CoordInfoLink"> + <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC2CJPF</span> + <span class="arrow">▼</span> </a> + </p> +
+</div> +<div id="dlgClipboard"> + <input type="text" class="TextFormat" /> + <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close"> + x</a> +</div> +<script type="text/javascript"> + $("a.CoordInfoLink").click(function (e) { + e.preventDefault(); + + $("#dlgClipboard") + .show() + .position({ + of: $("a.CoordInfoLink"), + my: "right top", + at: "right bottom", + offset: "0 5" + }) + .find("input") + .val('http://coord.info/' + $('.CoordInfoCode').text()) + .focus() + .select(); + + $(document).mouseup(function (e) { + if ($(e.target).parent("div#dlgClipboard").length == 0) { + $(this).unbind(e); + $("div#dlgClipboard").hide(); + } + }); + + return false; + }); + + +</script> + + + <div class="span-17"> + + <div class="span-17 last BottomSpacing" id="cacheDetails"> + <p class="cacheImage"> + <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/3.gif" alt="Multi-cache" title="Multi-cache" /></a> + </p> + + <h2 class="NoBottomSpacing"> + <span id="ctl00_ContentBody_CacheName">Kinderwald KiC</span> + </h2> + <div class="minorCacheDetails Clear"> + <div id="ctl00_ContentBody_mcd1"> + A cache by <a href="http://www.geocaching.com/profile/?guid=9a28b2fb-bce9-481f-87bc-7c5f4bafe723&wid=73246a5a-ebb9-4d4f-8db9-a951036f5376&ds=2">Tom03</a> + </div> + <div id="ctl00_ContentBody_mcd2"> + Hidden + : + 2010-07-31 + + </div> + <div> + + </div> + </div> + </div> + <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-6 BottomSpacing"> + + <dl> + <dt> + Difficulty:</dt> + <dd> + <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars2_5.gif" alt="2.5 out of 5" /></span> + </dd> + </dl> + <dl> + <dt> + Terrain:</dt> + <dd> + <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars2.gif" alt="2 out of 5" /></span> + </dd> + </dl> + + </div> + <div id="ctl00_ContentBody_size" class="CacheSize span-5"> + + <p class="AlignCenter"> + Size: <span class="minorCacheDetails"><img src="/images/icons/container/small.gif" alt="Size: small" title="Size: small" /> <small>(small)</small></span> + </p> + + </div> + <div class="span-6 right last"> + + + <div class="favorite right"> + <a id="uxFavContainerLink" href="javascript:void(0);"> + <div class="favorite-container"><!-- TODO! --> + <span class="favorite-value"> + 22 + </span> + Favorites + </div> + </a> + <div class="favorite-dropdown"> + + <ul> + <li> + <img id="imgFavoriteScore" src="/images/loading3.gif" width="20" height="20" alt="Loading" title="Loading"><span id="uxFavoriteScore"> </span> + </li> + <li> + <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="/seek/cache_favorited.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View Who Favorited this Cache</a> + </li> + <li> + <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a> + </li> + </ul> + </div> + </div> + + + </div> + + <p class="Clear"> + + <a id="ctl00_ContentBody_uxCacheUrl" title="Related Web Page" href="http://www.kinderwald.de/">Related Web Page</a> + + </p> + + + + <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable"> + <div class="LocationData FloatContainer"> + <div class="span-9"> + <p class="NoBottomSpacing"> + <a href="#" class="edit-cache-coordinates" id="uxLatLonLink" title="Correct these coordinates"> + <strong> + <span id="uxLatLon">N 52° 25.504 E 009° 39.852</span></strong> + </a> + <br /> + <span id="ctl00_ContentBody_LocationSubPanel"> + UTM: 32U E 545164 N 5808524<br /> + </span> + <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="/wpt/?lat=52.425067&lon=9.6642&detail=1" target="_blank">Other Conversions</a> + </p> + </div> + <div class="span-7 last AlignRight"> + <span id="ctl00_ContentBody_Location">In Niedersachsen, Germany</span><br /> + <span id="lblDistFromHome"><img src="/images/icons/compass/N.gif" alt="N" style="vertical-align:text-bottom" /> N 397.7 km from your home location</span> + </div> + </div> + <div class="DownloadLinks"> + <dl id="Print"> + <dt class="label"> + <span id="ctl00_ContentBody_uxPrintHeader">Print</span>: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376" target="_blank">No Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&lc=5" target="_blank">5 Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&lc=10" target="_blank">10 Logs</a> + <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=48.861002,9.186577 (Home Location)&daddr=52.425067,9.6642(Kinderwald+KiC)" target="_blank">Driving Directions</a> + </dd> + </dl> + <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;"> + <dt> + PDF: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a> + <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a> + <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a> + </dd> + </dl> + <dl id="Download"> + <dt class="label"> + <span id="ctl00_ContentBody_uxDownloadLabel">Download</span>: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="/software/default.aspx">Read about waypoint downloads</a> + </dd> + <dt></dt> + <dd> + <input type="submit" name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" /><input type="submit" name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" /><input type="submit" name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('73246a5a-ebb9-4d4f-8db9-a951036f5376');return false;" id="ctl00_ContentBody_btnSendToGPS" /><input type="submit" name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC2CJPF');return false;" id="ctl00_ContentBody_btnSendToPhone" /> + </dd> + </dl> + </div> + </div> + + <div class="Note Disclaimer"> + <strong> + Please note + </strong> + Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>. + </div> + + + <div class="Note PersonalCacheNote"> + <strong> + Personal Cache Note + </strong> + <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" /> + + <span id="cache_note"></span> + </div> + + <h3 class="CacheDescriptionHeader">Geocache Description:</h3> + <div class="UserSuppliedContent"> + <span id="ctl00_ContentBody_ShortDescription">Von Nachwuchs-Cachern für Nachwuchs-Cacher.
-</span>
-
- </div>
-
- <br />
- <div class="UserSuppliedContent">
-
+</span> + + </div> + + <br /> + <div class="UserSuppliedContent"> + <span id="ctl00_ContentBody_LongDescription">Kleiner Multi über 7 Stationen. Länge ca. 1 km + 1km für den Rückweg. Die ZS befinden sich alle am KLEINEN BACH innerhalb des Kinderwaldes. Die Fragen müssen nicht in der aufgeführten Reihenfolge beantwortet werden, ihr könnt auch mit der letzten Frage anfangen !<br />
<br />
Nähere Infos zum Kinderwald gibt es unter <a href="http://www.kinderwald.de/" target="_blank" rel="nofollow">www.kinderwald.de</a><br />
@@ -619,916 +534,856 @@ F=H+A-B-C<br /> <br />
Viel Spaß !<br />
<br />
-P.S. An warmen Tagen Badesachen und Handtuch mitnehmen.</span>
-
- </div>
-
- <p>
-
-
- </p>
- <p id="ctl00_ContentBody_hints">
- <strong>
- Additional Hints</strong>
- (<a id="ctl00_ContentBody_lnkDH" onclick="dht(this);return false;" title="Decrypt" href="../seek/#">Decrypt</a>) </p><div id="div_hint" class="span-8 WrapFix">
- Qnf Svany vfg hagre Fgrvara</div><div id='dk' style="display: block;" class="span-9 last">
- <span id="ctl00_ContentBody_EncryptionKey" class="right"><div class="DecryptionKeyWidget"> <p class="WidgetHeader">Decryption Key</p> <p class="WidgetBody">A|B|C|D|E|F|G|H|I|J|K|L|M<br /> -------------------------<br /> N|O|P|Q|R|S|T|U|V|W|X|Y|Z</p> <p class="WidgetFooter">(letter above equals below, and vice versa)</p></div></span>
- </div>
- <div class="Clear">
- </div>
-
- </div>
-
-
- <div class="span-6 prepend-1 last">
-
-
-<div class="CacheDetailNavigation NoPrint">
-
- <a href="/seek/log.aspx?ID=1811409&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log your visit</a>
- <ul>
- <li><a href="/seek/gallery.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View Gallery</a> (17)</li>
- <li><a href="/my/watchlist.aspx?w=1811409">Watch</a> (3)</li>
- <li><a href="/bookmarks/mark.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&WptTypeID=3">Bookmark</a></li>
- <li><a href="/bookmarks/ignore.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&WptTypeID=3">Ignore</a></li>
- </ul>
-
-</div>
-
-
-
-
- <div id="map_preview_canvas" class="TopSpacing" style="width: 228px; height: 175px;">
- </div>
-
-
-
- <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing">
-
- <h3 class="WidgetHeader">
- Attributes
- </h3>
- <div class="WidgetBody">
- <img src="/images/attributes/motorcycles-no.gif" alt="no motorcycles" title="no motorcycles" width="30" height="30" /> <img src="/images/attributes/wheelchair-no.gif" alt="not wheelchair accessible" title="not wheelchair accessible" width="30" height="30" /> <img src="/images/attributes/winter-yes.gif" alt="available in winter" title="available in winter" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/wading-yes.gif" alt="may require wading" title="may require wading" width="30" height="30" /> <img src="/images/attributes/scenic-yes.gif" alt="scenic view" title="scenic view" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/kids-yes.gif" alt="kid friendly" title="kid friendly" width="30" height="30" /> <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p>
- </div>
-
- </div>
-
-
+P.S. An warmen Tagen Badesachen und Handtuch mitnehmen.</span> + + </div> + + <p> + + + </p> + <p id="ctl00_ContentBody_hints"> + <strong> + Additional Hints</strong> + (<a id="ctl00_ContentBody_lnkDH" onclick="dht(this);return false;" title="Decrypt" href="../seek/#">Decrypt</a>) </p><div id="div_hint" class="span-8 WrapFix"> + Qnf Svany vfg hagre Fgrvara</div><div id='dk' style="display: block;" class="span-9 last"> + <span id="ctl00_ContentBody_EncryptionKey" class="right"><div class="DecryptionKeyWidget"> <p class="WidgetHeader">Decryption Key</p> <p class="WidgetBody">A|B|C|D|E|F|G|H|I|J|K|L|M<br /> -------------------------<br /> N|O|P|Q|R|S|T|U|V|W|X|Y|Z</p> <p class="WidgetFooter">(letter above equals below, and vice versa)</p></div></span> + </div> + <div class="Clear"> + </div> + + </div> + + + <div class="span-6 prepend-1 last"> + + +<div class="CacheDetailNavigation NoPrint"> + + <a href="/seek/log.aspx?ID=1811409&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log your visit</a> + <ul> + <li><a href="/seek/gallery.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View Gallery</a> (21)</li> + <li><a href="/my/watchlist.aspx?w=1811409">Watch</a> (2)</li> + <li><a href="/bookmarks/mark.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&WptTypeID=3">Bookmark</a></li> + <li><a href="/bookmarks/ignore.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&WptTypeID=3">Ignore</a></li> + </ul> + + +</div> + + + + + <div id="map_preview_canvas" class="TopSpacing" style="width: 228px; height: 175px;"> + </div> + + + + <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing"> + + <h3 class="WidgetHeader"> + Attributes + </h3> + <div class="WidgetBody"> + <img src="/images/attributes/wheelchair-no.gif" alt="not wheelchair accessible" title="not wheelchair accessible" width="30" height="30" /> <img src="/images/attributes/motorcycles-no.gif" alt="no motorcycles" title="no motorcycles" width="30" height="30" /> <img src="/images/attributes/winter-yes.gif" alt="available in winter" title="available in winter" width="30" height="30" /> <img src="/images/attributes/firstaid-yes.gif" alt="needs maintenance" title="needs maintenance" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/wading-yes.gif" alt="may require wading" title="may require wading" width="30" height="30" /> <img src="/images/attributes/scenic-yes.gif" alt="scenic view" title="scenic view" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/kids-yes.gif" alt="kid friendly" title="kid friendly" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p> + </div> + + </div> + + <div id="ctl00_ContentBody_uxBanManWidget" class="InlinePageAds">
-
-
+ + <script type='text/javascript'>
googletag.cmd.push(function() {{
-googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_225de53b-b8eb-40c9-9d52-b39f5e133112').addService(googletag.pubads());
+googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_0163cb95-87d0-4db8-837c-4f1ceb127478').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
}});
</script>
-<div id='div_225de53b-b8eb-40c9-9d52-b39f5e133112'>
+<div id='div_0163cb95-87d0-4db8-837c-4f1ceb127478'>
<script type='text/javascript'>
-googletag.cmd.push(function() { googletag.display('div_225de53b-b8eb-40c9-9d52-b39f5e133112'); });
+googletag.cmd.push(function() { googletag.display('div_0163cb95-87d0-4db8-837c-4f1ceb127478'); });
</script>
</div>
-
- <p>
+ + <p> <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small> </p>
-</div><div class="GoogleAds AlignCenter BottomSpacing">
-
- </div>
- <div class="clear">
- </div>
-
- <span id="ctl00_ContentBody_lnkTravelBugs"></span>
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">
- <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span>
- </h3>
- <div class="WidgetBody">
-
-
+</div><div class="GoogleAds AlignCenter BottomSpacing"> + + </div> + <div class="clear"> + </div> + + <span id="ctl00_ContentBody_lnkTravelBugs"></span> + + +<div class="CacheDetailNavigationWidget"> + + <h3 class="WidgetHeader"> + <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span> + </h3> + <div class="WidgetBody"> + + <div id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItems">
-
- <p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p>
-
-</div>
- <div class="TopSpacing">
-
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View past Trackables</a></p>
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p>
- </div>
-
-
- </div>
-
-
-</div>
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">Bookmark Lists</h3>
- <div class="WidgetBody">
-
-
- <ul class="BookmarkList">
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=3eeea057-f605-485a-a45a-f5fea1426612">Kindercaches (KiC)</a><br /> by <a href="http://www.geocaching.com/profile/?guid=0564a940-8311-40ee-8e76-7e91b2cf6284">blafoo</a>
- </li>
-
- </ul>
-
- <p class="NoBottomSpacing">
- <a href="/bookmarks/default.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&WptTypeID=3" title="View all bookmark lists...">View all bookmark lists...</a>
- </p>
-
- </div>
-
-
-</div>
-
-
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">My Bookmark Lists</h3>
- <div class="WidgetBody">
-
-
- <ul class="BookmarkList">
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=14551708-0c3c-4f95-9342-1bb3119e6efe">cgeo mocks</a><br /> by <a href="http://www.geocaching.com/profile/?guid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">JoSaMaJa</a>
- </li>
-
- </ul>
-
- <p class="NoBottomSpacing">
-
- </p>
-
- </div>
-
-
-</div>
-
-
-
-
- </div>
-
-
- <div id="ctl00_ContentBody_bottomSection" class="span-24 last">
-
- <p>
- <span id="ctl00_ContentBody_WaypointsInfo" style="font-weight:bold;">Additional Waypoints</span> <br />
-
-
-<script type="text/javascript">
- <!--
- var checkflag = false;
- function checkAll(obj) {
- if (checkflag == false) {
- checkflag = true;
- } else {
- checkflag = false;
- }
- var arrInput = document.getElementsByTagName("input");
- for (i = 0; i < arrInput.length; i++) {
- if (arrInput[i].type == 'checkbox') {
- arrInput[i].checked = checkflag;
- }
- }
- }
-
- // End -->
-</script>
-
- <table class="Table" id="ctl00_ContentBody_Waypoints">
- <thead>
- <tr>
- <th scope="col" class="AlignCenter">
- <a href="javascript:checkAll(this);">
- </a>
- </th>
- <th scope="col">
-
- </th>
- <th scope="col">
-
- </th>
- <th scope="col">
- Prefix
- </th>
- <th scope="col">
- Lookup
- </th>
- <th scope="col">
- Name
- </th>
- <th scope="col">
- Coordinate
- </th>
- <th scope="col">
-
- </th>
- </tr>
- </thead>
- <tbody>
-
- <tr class="BorderBottom " ishidden="false">
- <td class="AlignCenter">
-
- </td>
- <td>
- <img width="16" height="16" src="/images/icons/icon_nocoords.jpg" alt="Hide Coordinates" title="Hide Coordinates" />
- </td>
- <td>
- <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/flag.jpg" alt="Final Location" title="Final Location" />
- </td>
- <td>
- <span id="awpt_FN">
- FN</span>
- </td>
- <td>
- FINAL
- </td>
- <td>
- <a href="http://www.geocaching.com/seek/wpt.aspx?WID=30f1b37c-d395-4c7a-94e2-0c649d5f231b&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">GC2CJPF Final</a> (Final Location)
- </td>
- <td>
- ???
-
- </td>
- <td>
-
-
-
-
- </td>
- </tr>
- <tr class="BorderBottom ">
- <td>
-
- </td>
- <td>
- Note:
- </td>
- <td colspan="6">
-
- </td>
- </tr>
-
- <tr class="BorderBottom AlternatingRow" ishidden="false">
- <td class="AlignCenter">
-
- </td>
- <td>
- <img width="16" height="16" src="/images/icons/icon_viewable.jpg" alt="Visible" title="Visible" />
- </td>
- <td>
- <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/pkg.jpg" alt="Parking Area" title="Parking Area" />
- </td>
- <td>
- <span id="awpt_PK">
- PK</span>
- </td>
- <td>
- PARKNG
- </td>
- <td>
- <a href="http://www.geocaching.com/seek/wpt.aspx?WID=98cb1387-49ce-4f94-9b05-5cb079d332b1&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">GC2CJPF Parking</a> (Parking Area)
- </td>
- <td>
- N 52° 25.384 E 009° 39.023
-
- </td>
- <td>
-
-
-
-
- </td>
- </tr>
- <tr class="BorderBottom AlternatingRow">
- <td>
-
- </td>
- <td>
- Note:
- </td>
- <td colspan="6">
- Kein "offizieller" Parkplatz, Parken trotzdem möglich.
- </td>
- </tr>
-
- <tr class="BorderBottom " ishidden="false">
- <td class="AlignCenter">
-
- </td>
- <td>
- <img width="16" height="16" src="/images/icons/icon_viewable.jpg" alt="Visible" title="Visible" />
- </td>
- <td>
- <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/puzzle.jpg" alt="Question to Answer" title="Question to Answer" />
- </td>
- <td>
- <span id="awpt_ST">
- ST</span>
- </td>
- <td>
- START
- </td>
- <td>
- <a href="http://www.geocaching.com/seek/wpt.aspx?WID=04113bad-64ca-499a-9848-b5937e13da1b&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">GC2CJPF Start</a> (Question to Answer)
- </td>
- <td>
- N 52° 25.504 E 009° 39.852
-
- </td>
- <td>
-
-
-
-
- </td>
- </tr>
- <tr class="BorderBottom ">
- <td>
-
- </td>
- <td>
- Note:
- </td>
- <td colspan="6">
-
- </td>
- </tr>
-
- <tr class="BorderBottom AlternatingRow" ishidden="false">
- <td class="AlignCenter">
-
- </td>
- <td>
- <img width="16" height="16" src="/images/icons/icon_viewable.jpg" alt="Visible" title="Visible" />
- </td>
- <td>
- <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/waypoint.jpg" alt="Reference Point" title="Reference Point" />
- </td>
- <td>
- <span id="awpt_WO">
- WO</span>
- </td>
- <td>
- SCENIC
- </td>
- <td>
- <a href="http://www.geocaching.com/seek/wpt.aspx?WID=b28c5879-3181-4510-94fa-6ec5e30fd056&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">Aussichtspunkt</a> (Reference Point)
- </td>
- <td>
- N 52° 25.488 E 009° 39.432
-
- </td>
- <td>
-
-
-
-
- </td>
- </tr>
- <tr class="BorderBottom AlternatingRow">
- <td>
-
- </td>
- <td>
- Note:
- </td>
- <td colspan="6">
- Ehemalige Finallocation wo es gebrannt hat. Gleichzeitig netter Aussichtspunkt.
- </td>
- </tr>
-
- </tbody> </table>
-
-<p>
-
- <span id="ShowHideLink">|
- <a id="ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates" href="../controls/#">Show Hidden Waypoints</a>
- <a id="ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates" href="../controls/#">Hide Hidden Waypoints</a></span>
-</p>
-
-<script type="text/javascript" language="javascript">
- var hiddenLinkCookieName = "hiddenlinks";
-
- jQuery(function () {
- var $ = jQuery;
- var hiddenLinkCookie = jQuery.cookie(hiddenLinkCookieName);
-
- $('#ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates').click(function (e) {
- setHiddenCoordState(true);
- return false;
- });
-
- $('#ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates').click(function (e) {
- setHiddenCoordState(false);
- return false;
- });
-
- if ($("#ctl00_ContentBody_Waypoints tbody tr[ishidden='true']").length > 0) {
- $("#ShowHideLink").show();
- } else {
- $("#ShowHideLink").hide();
- }
-
- if (hiddenLinkCookie == null || hiddenLinkCookie == "false") {
- setHiddenCoordState(false);
- } else {
- setHiddenCoordState(true);
- }
-
- });
-
-
-
- function setHiddenCoordState(show) {
- var $ = jQuery;
- if (show) {
- $('#ctl00_ContentBody_Waypoints tbody')
- .find("tr.AlternatingRow")
- .removeClass("AlternatingRow")
- .end()
- .find("tr")
- .show()
- .end()
- .find("tr:even:visible")
- .each(function(i) {
- if (i % 2 == 1)
- $(this).addClass("AlternatingRow").next().addClass("AlternatingRow");
- })
- .end();
-
- $("#ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates").hide();
- $("#ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates").show();
-
- $.cookie(hiddenLinkCookieName, "true");
-
- } else {
- $('#ctl00_ContentBody_Waypoints tbody')
- .find("tr.AlternatingRow")
- .removeClass("AlternatingRow")
- .end()
- .find("tr[ishidden='true']").each(function() {
- $(this).hide().next().hide();
- })
- .end()
- .find("tr:even:visible")
- .each(function(i) {
- if (i % 2 == 1)
- $(this).addClass("AlternatingRow").next().addClass("AlternatingRow");
- })
- .end();
-
- $("#ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates").show();
- $("#ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates").hide();
-
- $.cookie(hiddenLinkCookieName, "false");
- }
-
- return false;
- }
-</script>
-
- <p>
+ + <p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p> +
+</div> + <div class="TopSpacing"> + + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View past Trackables</a></p> + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p> + </div> + + + </div> + + +</div> + + +<div class="CacheDetailNavigationWidget"> + <h3 class="WidgetHeader"> + Bookmark Lists + </h3> + <div class="WidgetBody"> + + <ul class="BookmarkList"> + + <li class=''> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=3eeea057-f605-485a-a45a-f5fea1426612">Kindercaches (KiC)</a><br />by <a href="http://www.geocaching.com/profile/?guid=0564a940-8311-40ee-8e76-7e91b2cf6284">blafoo</a> + </li> + + <li class='AlternatingRow'> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=15167f05-1058-4b5a-8f80-d9d12469006d">Interessante GC und NC Raum Hannover</a><br />by <a href="http://www.geocaching.com/profile/?guid=89b95797-bede-4ab2-990e-3ae1fd97539f">Tinimaus</a> + </li> + + </ul> + + <p class="NoBottomSpacing"> + <a href="/bookmarks/default.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376&WptTypeID=3" title="View all bookmark lists...">View all bookmark lists...</a> + </p> + </div> +</div> + + + + + </div> + + + <div id="ctl00_ContentBody_bottomSection" class="span-24 last"> + + <p> + <span id="ctl00_ContentBody_WaypointsInfo" style="font-weight:bold;">Additional Waypoints</span> <br /> + + +<script type="text/javascript"> + <!-- + var checkflag = false; + function checkAll(obj) { + if (checkflag == false) { + checkflag = true; + } else { + checkflag = false; + } + var arrInput = document.getElementsByTagName("input"); + for (i = 0; i < arrInput.length; i++) { + if (arrInput[i].type == 'checkbox') { + arrInput[i].checked = checkflag; + } + } + } + + // End --> +</script> + + <table class="Table" id="ctl00_ContentBody_Waypoints"> + <thead> + <tr> + <th scope="col" class="AlignCenter"> + <a href="javascript:checkAll(this);"> + </a> + </th> + <th scope="col"> + + </th> + <th scope="col"> + + </th> + <th scope="col"> + Prefix + </th> + <th scope="col"> + Lookup + </th> + <th scope="col"> + Name + </th> + <th scope="col"> + Coordinate + </th> + <th scope="col"> + + </th> + </tr> + </thead> + <tbody> + + <tr class="BorderBottom " ishidden="false"> + <td class="AlignCenter"> + + </td> + <td> + <img width="16" height="16" src="/images/icons/icon_nocoords.jpg" alt="Hide Coordinates" title="Hide Coordinates" /> + </td> + <td> + <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/flag.jpg" alt="Final Location" title="Final Location" /> + </td> + <td> + <span id="awpt_FN"> + FN</span> + </td> + <td> + FINAL + </td> + <td> + <a href="http://www.geocaching.com/seek/wpt.aspx?WID=30f1b37c-d395-4c7a-94e2-0c649d5f231b&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">GC2CJPF Final</a> (Final Location) + </td> + <td> + ??? + + </td> + <td> + + + + + </td> + </tr> + <tr class="BorderBottom "> + <td> + + </td> + <td> + Note: + </td> + <td colspan="6"> + + </td> + </tr> + + <tr class="BorderBottom AlternatingRow" ishidden="false"> + <td class="AlignCenter"> + + </td> + <td> + <img width="16" height="16" src="/images/icons/icon_viewable.jpg" alt="Visible" title="Visible" /> + </td> + <td> + <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/pkg.jpg" alt="Parking Area" title="Parking Area" /> + </td> + <td> + <span id="awpt_PK"> + PK</span> + </td> + <td> + PARKNG + </td> + <td> + <a href="http://www.geocaching.com/seek/wpt.aspx?WID=98cb1387-49ce-4f94-9b05-5cb079d332b1&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">GC2CJPF Parking</a> (Parking Area) + </td> + <td> + N 52° 25.384 E 009° 39.023 + + </td> + <td> + + + + + </td> + </tr> + <tr class="BorderBottom AlternatingRow"> + <td> + + </td> + <td> + Note: + </td> + <td colspan="6"> + Kein "offizieller" Parkplatz, Parken trotzdem möglich. + </td> + </tr> + + <tr class="BorderBottom " ishidden="false"> + <td class="AlignCenter"> + + </td> + <td> + <img width="16" height="16" src="/images/icons/icon_viewable.jpg" alt="Visible" title="Visible" /> + </td> + <td> + <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/puzzle.jpg" alt="Virtual Stage" title="Virtual Stage" /> + </td> + <td> + <span id="awpt_ST"> + ST</span> + </td> + <td> + START + </td> + <td> + <a href="http://www.geocaching.com/seek/wpt.aspx?WID=04113bad-64ca-499a-9848-b5937e13da1b&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">GC2CJPF Start</a> (Virtual Stage) + </td> + <td> + N 52° 25.504 E 009° 39.852 + + </td> + <td> + + + + + </td> + </tr> + <tr class="BorderBottom "> + <td> + + </td> + <td> + Note: + </td> + <td colspan="6"> + + </td> + </tr> + + <tr class="BorderBottom AlternatingRow" ishidden="false"> + <td class="AlignCenter"> + + </td> + <td> + <img width="16" height="16" src="/images/icons/icon_viewable.jpg" alt="Visible" title="Visible" /> + </td> + <td> + <img width="16" height="16" src="http://www.geocaching.com/images/wpttypes/sm/waypoint.jpg" alt="Reference Point" title="Reference Point" /> + </td> + <td> + <span id="awpt_WO"> + WO</span> + </td> + <td> + SCENIC + </td> + <td> + <a href="http://www.geocaching.com/seek/wpt.aspx?WID=b28c5879-3181-4510-94fa-6ec5e30fd056&RefID=73246a5a-ebb9-4d4f-8db9-a951036f5376&RefDS=1">Aussichtspunkt</a> (Reference Point) + </td> + <td> + N 52° 25.488 E 009° 39.432 + + </td> + <td> + + + + + </td> + </tr> + <tr class="BorderBottom AlternatingRow"> + <td> + + </td> + <td> + Note: + </td> + <td colspan="6"> + Ehemalige Finallocation wo es gebrannt hat. Gleichzeitig netter Aussichtspunkt. + </td> + </tr> + + </tbody> </table> + +<p> + + <span id="ShowHideLink">| + <a id="ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates" href="../controls/#">Show Hidden Waypoints</a> + <a id="ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates" href="../controls/#">Hide Hidden Waypoints</a></span> +</p> + +<script type="text/javascript" language="javascript"> + var hiddenLinkCookieName = "hiddenlinks"; + + jQuery(function () { + var $ = jQuery; + var hiddenLinkCookie = jQuery.cookie(hiddenLinkCookieName); + + $('#ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates').click(function (e) { + setHiddenCoordState(true); + return false; + }); + + $('#ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates').click(function (e) { + setHiddenCoordState(false); + return false; + }); + + if ($("#ctl00_ContentBody_Waypoints tbody tr[ishidden='true']").length > 0) { + $("#ShowHideLink").show(); + } else { + $("#ShowHideLink").hide(); + } + + if (hiddenLinkCookie == null || hiddenLinkCookie == "false") { + setHiddenCoordState(false); + } else { + setHiddenCoordState(true); + } + + }); + + + + function setHiddenCoordState(show) { + var $ = jQuery; + if (show) { + $('#ctl00_ContentBody_Waypoints tbody') + .find("tr.AlternatingRow") + .removeClass("AlternatingRow") + .end() + .find("tr") + .show() + .end() + .find("tr:even:visible") + .each(function(i) { + if (i % 2 == 1) + $(this).addClass("AlternatingRow").next().addClass("AlternatingRow"); + }) + .end(); + + $("#ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates").hide(); + $("#ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates").show(); + + $.cookie(hiddenLinkCookieName, "true"); + + } else { + $('#ctl00_ContentBody_Waypoints tbody') + .find("tr.AlternatingRow") + .removeClass("AlternatingRow") + .end() + .find("tr[ishidden='true']").each(function() { + $(this).hide().next().hide(); + }) + .end() + .find("tr:even:visible") + .each(function(i) { + if (i % 2 == 1) + $(this).addClass("AlternatingRow").next().addClass("AlternatingRow"); + }) + .end(); + + $("#ctl00_ContentBody_Waypoints_uxShowHiddenCoordinates").show(); + $("#ctl00_ContentBody_Waypoints_uxHideHiddenCoordinates").hide(); + + $.cookie(hiddenLinkCookieName, "false"); + } + + return false; + } +</script> + + <p> <div id="uxlrgMap" class="FloatRight TopSpacing">
-
- <div class="PageBreakBefore">
-
- </div>
- <div class="CDMapWidget">
- <p class="WidgetHeader NoBottomSpacing">
- <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="/map/default.aspx?lat=52.425067&lng=9.6642" target="_blank">View Larger Map</a>
- </p>
-
- <div id="map_canvas" style="width: 325px; height: 325px;">
- </div>
- <p class="WidgetFooter">
- <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a>
- </p>
- </div>
- <div style="display: none;">
- <div id="mapPrintingNotes">
- To print the map in Firefox and Opera, enable background images in the print dialog.
- <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()">
- Close
- </a>
- </div>
- </div>
-
-</div>
+ + <div class="PageBreakBefore"> + + </div> + <div class="CDMapWidget"> + <p class="WidgetHeader NoBottomSpacing"> + <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="/map/default.aspx?lat=52.425067&lng=9.6642" target="_blank">View Larger Map</a> + </p> + + <div id="map_canvas" style="width: 325px; height: 325px;"> + </div> + <p class="WidgetFooter"> + <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a> + </p> + </div> + <div style="display: none;"> + <div id="mapPrintingNotes"> + To print the map in Firefox and Opera, enable background images in the print dialog. + <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()"> + Close + </a> + </div> + </div> - <p class="NoPrint">
- <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span>
- <br />
- <span id="ctl00_ContentBody_FindText"></span>
- </p>
- <ul class="NoPrint">
- <li>
- ...other caches <a href="/seek/nearest.aspx?u=Tom03">hidden</a> or <a href="/seek/nearest.aspx?ul=Tom03">found</a> by this user
- </li>
-
- <li>
- ...nearby <a href="/seek/nearest.aspx?tx=a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74&lat=52.425067&lng=9.664200">caches of this type</a>, <a href="/seek/nearest.aspx?tx=a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74&lat=52.425067&lng=9.664200&f=1">that I haven't found</a>
- </li>
- <li>
- ...all nearby <a href="/seek/nearest.aspx?lat=52.425067&lng=9.664200">caches</a>, <a href="/seek/nearest.aspx?lat=52.425067&lng=9.664200&f=1">that I haven't found</a>
- </li>
- <li>
- ...all nearby <a href="http://www.waymarking.com/directory.aspx?f=1&lat=52.425067&lon=9.664200">waymarks on Waymarking.com</a>
- </li>
-
-
- </ul>
- <p class="NoPrint">
- <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span>
- </p>
- <span class="NoPrint">
-
-<ul>
- <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=52.42507&lng=9.6642" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+52%c2%b0+25.504+E+009%c2%b0+39.852+(GC2CJPF)+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=52.42507&longitude=9.6642&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=52.42507&lon=9.6642&zoom=16&q=52.42507,9.6642&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.52.42507_9.6642_GC2CJPF" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=52.42507&lon=9.6642" target="_blank">OpenCycleMap</a></li><li><a href="http://www.openstreetmap.org/?mlat=52.42507&mlon=9.6642&zoom=12" target="_blank">OpenStreetMap</a></li></span>
-</ul>
+</div> + + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span> + <br /> + <span id="ctl00_ContentBody_FindText"></span> + </p> + <ul class="NoPrint"> + <li> + ...other caches <a href="/seek/nearest.aspx?u=Tom03">hidden</a> or <a href="/seek/nearest.aspx?ul=Tom03">found</a> by this user + </li> + + <li> + ...nearby <a href="/seek/nearest.aspx?tx=a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74&lat=52.425067&lng=9.664200">caches of this type</a>, <a href="/seek/nearest.aspx?tx=a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74&lat=52.425067&lng=9.664200&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a href="/seek/nearest.aspx?lat=52.425067&lng=9.664200">caches</a>, <a href="/seek/nearest.aspx?lat=52.425067&lng=9.664200&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a href="http://www.waymarking.com/directory.aspx?f=1&lat=52.425067&lon=9.664200">waymarks on Waymarking.com</a> + </li> + + + </ul> + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span> + </p> + <span class="NoPrint"> + +<ul> + <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=52.42507&lng=9.6642" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+52%c2%b0+25.504+E+009%c2%b0+39.852+(GC2CJPF)+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=52.42507&longitude=9.6642&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=52.42507&lon=9.6642&zoom=16&q=52.42507,9.6642&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.52.42507_9.6642_GC2CJPF" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=52.42507&lon=9.6642" target="_blank">OpenCycleMap</a></li><li><a href="http://www.openstreetmap.org/?mlat=52.42507&mlon=9.6642&zoom=12" target="_blank">OpenStreetMap</a></li></span> +</ul> + + </span> + <ul class="CachePageImages NoPrint"> + + </ul> + + <div class="InformationWidget Clear"> + <h3> + 218 Logged Visits + </h3> + <div class="EncryptDecrypt"> + <a href="#" class="decrypt-link"> + Decrypt + </a> + </div> + <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 195 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 4 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 8 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 2 <img src="/images/logtypes/23.png" alt="Enable Listing" title="Enable Listing" /> 2 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 <img src="/images/logtypes/45.png" alt="Needs Maintenance" title="Needs Maintenance" /> 3 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 3 </p></span> + <p class="HalfLeft"> + <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View Logbook</a> | <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View the Image Gallery of 21 images</a> + </p> + <p class="NoBottomSpacing AlignRight"> + <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links. + </p> + </div> + + <div id="cache_logs_container"> + <table id="cache_logs_table" class="LogsTable NoBottomSpacing"> + <tbody> + </tbody> + <tfoot> + <tr> + <td class="AlignCenter"> + <div id="pnlLazyLoad" style="display: none;"> + <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" /> + Loading Cache Logs... + </div> + <div id="pnlButtonLoad" style="display: none;"> + <a class="MobileButton"> + Load More Logs...</a> + </div> + </td> + </tr> + </tfoot> + </table> + </div> + <p> + <small> + Current Time: <time datetime="2015-03-31T10:40:16Z">03/31/2015 10:40:16 Pacific Daylight Time (17:40 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2015-02-08T18:40:31Z">2015-02-08T18:40:31Z</time> on 02/08/2015 10:40:31 (UTC-08:00) Pacific Time (US & Canada) (18:40 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum + </small> + </p> + <div id="topScroll" class="TopScroll" style="display: none;"> + <a href="#Top"> </a> </div></div><script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl"> + <tr class="log-row" data-encoded="${IsEncoded}"> + <td> + <div class="FloatLeft LogDisplayLeft"> + <p class="logOwnerProfileName"> + <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong> + </p> + <p class="logOwnerBadge"> + <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle} + </p> + <p class="logOwnerAvatar"> + <a href="/profile/?guid=${AccountGuid}">{{if includeAvatars && AvatarImage}} + <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}"> + {{else includeAvatars }} + <img width="48" height="48" src="/images/default_avatar.jpg"> + {{/if}} + </a> + </p> + <p class="logOwnerStats"> + {{if GeocacheFindCount > 0 }} + <img title="Caches Found" src="/images/icons/16/found.png">${GeocacheFindCount} + {{/if}} + </p> + </div> + <div class="FloatLeft LogDisplayRight"> + <div class="HalfLeft LogType"> + <strong> + <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong> + </div> + <div class="HalfRight AlignRight"> + <span class="minorDetails LogDate">${Visited}</span> + </div> + <div class="Clear LogContent"> + {{if LatLonString.length > 0}} + <strong>${LatLonString}</strong> + {{/if}} + <p class="LogText">{{html LogText}}</p> + {{if Images.length > 0}} + <table cellspacing="0" cellpadding="3" class="LogImagesTable"> + {{tmpl(Images) "tmplCacheLogImages"}} + </table> + {{/if}} + + <div class="AlignRight"> + <small><a title="View Log" href="/seek/log.aspx?LUID=${LogGuid}" target="_blank">{{if (userInfo.ID==AccountID)}} + View / Edit Log / Images + {{else}} + View Log + {{/if}} + </a></small> + {{if (userInfo.ID==AccountID)}} + <small><a title="Upload Image" href="/seek/upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small> + {{/if}} + </div> + </div> + </div> + </td> + </tr> + </script><script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl"> + <tr> + <td> + + <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}"> + <img title="Photo" alt="Photo" src="/images/icons/16/photo.png"> + <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span> + </a> + </td> + </tr> + </script><script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl"> + <span class="LogImgTitle"> ${ $('<div /> + ').text($('<div /> + ').text($('<div /> + ').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink"> + + <a target="_blank" href="/seek/log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a> + + <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span> + + {{if (Descr && Descr.length > 0) }} + <br /><p class="LogImgDescription">${ $('<div /> + ').text($('<div /> + ').text($('<div /> + ').html($item.data.Descr).text()).html()).html() }</p> + {{/if}} + </script><script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl"> + <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}"> + <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4> + <dl> + <dt>Original:</dt> + <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd> + </dl> + <dl class="ccu-parse"> + <dt>Change To:</dt> + <dd> + <input type="text" max="40" size="35" class="cc-parse-text"> + <button class="ccu-button ccu-parse">Submit</button> + </dd> + </dl> + <dl class="ccu-parseverify" style="display: none;"> + <dt>Change To:</dt> + <dd> + <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span> + </dd> + <dt> </dt> + <dd> + <button class="ccu-button ccu-parseverify-accept">Accept</button> + <button class="ccu-button ccu-parseverify-cancel">Cancel</button> + </dd> + </dl> + </div> + </script> - </span>
- <ul class="CachePageImages NoPrint">
-
- </ul>
-
- <div class="InformationWidget Clear">
- <h3>
- 171 Logged Visits
- </h3>
- <div class="EncryptDecrypt">
- <a href="#" class="decrypt-link">
- Decrypt
- </a>
</div>
- <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 151 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 3 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 7 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 2 <img src="/images/logtypes/23.png" alt="Enable Listing" title="Enable Listing" /> 2 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 <img src="/images/logtypes/45.png" alt="Needs Maintenance" title="Needs Maintenance" /> 2 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 3 </p></span>
- <p class="HalfLeft">
- <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View Logbook</a>Â |Â <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=73246a5a-ebb9-4d4f-8db9-a951036f5376">View the Image Gallery of 17 images</a>
- </p>
- <p class="NoBottomSpacing AlignRight">
- <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links.
- </p>
- </div>
-
- <div id="cache_logs_container">
- <table id="cache_logs_table" class="LogsTable NoBottomSpacing">
- <tbody>
- </tbody>
- <tfoot>
- <tr>
- <td class="AlignCenter">
- <div id="pnlLazyLoad" style="display: none;">
- <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" />
- Loading Cache Logs...
- </div>
- <div id="pnlButtonLoad" style="display: none;">
- <a class="MobileButton">
- Load More Logs...</a>
- </div>
- </td>
- </tr>
- </tfoot>
- </table>
- </div>
- <p>
- <small>
- Current Time: <time datetime="2013-08-21T21:11:12Z">08/21/2013 21:11:12 Pacific Daylight Time (04:11 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2013-08-05T15:44:42Z">2013-08-05T15:44:42Z</time> on 08/05/2013 08:44:42 Pacific Daylight Time (15:44 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum
- </small>
- </p>
- <div id="topScroll" class="TopScroll" style="display: none;">
- <a href="#Top"> </a> </div></div><script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl">
- <tr class="log-row" data-encoded="${IsEncoded}">
- <td>
- <div class="FloatLeft LogDisplayLeft">
- <p class="logOwnerProfileName">
- <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong>
- </p>
- <p class="logOwnerBadge">
- <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle}
- </p>
- <p class="logOwnerAvatar">
- <a href="/profile/?guid=${AccountGuid}">{{if includeAvatars && AvatarImage}}
- <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}">
- {{else includeAvatars }}
- <img width="48" height="48" src="/images/default_avatar.jpg">
- {{/if}}
- </a>
- </p>
- <p class="logOwnerStats">
- {{if GeocacheFindCount > 0 }}
- <img title="Caches Found" src="/images/icons/16/found.png">${GeocacheFindCount}
- {{/if}}
- </p>
- </div>
- <div class="FloatLeft LogDisplayRight">
- <div class="HalfLeft LogType">
- <strong>
- <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong>
- </div>
- <div class="HalfRight AlignRight">
- <span class="minorDetails LogDate">${Visited}</span>
- </div>
- <div class="Clear LogContent">
- {{if LatLonString.length > 0}}
- <strong>${LatLonString}</strong>
- {{/if}}
- <p class="LogText">{{html LogText}}</p>
- {{if Images.length > 0}}
- <table cellspacing="0" cellpadding="3" class="LogImagesTable">
- {{tmpl(Images) "tmplCacheLogImages"}}
- </table>
- {{/if}}
-
- <div class="AlignRight">
- <small><a title="View Log" href="/seek/log.aspx?LUID=${LogGuid}" target="_blank">{{if (userInfo.ID==AccountID)}}
- View / Edit Log / Images
- {{else}}
- View Log
- {{/if}}
- </a></small>
- {{if (userInfo.ID==AccountID)}}
- <small><a title="Upload Image" href="/seek/upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small>
- {{/if}}
- </div>
- </div>
- </div>
- </td>
- </tr>
- </script><script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl">
- <tr>
- <td>
-
- <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}">
- <img title="Photo" alt="Photo" src="/images/icons/16/photo.png">
- <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span>
- </a>
- </td>
- </tr>
- </script><script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl">
- <span class="LogImgTitle"> ${ $('<div />
- ').text($('<div />
- ').text($('<div />
- ').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink">
-
- <a target="_blank" href="/seek/log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a>
-
- <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span>
-
- {{if (Descr && Descr.length > 0) }}
- <br /><p class="LogImgDescription">${ $('<div />
- ').text($('<div />
- ').text($('<div />
- ').html($item.data.Descr).text()).html()).html() }</p>
- {{/if}}
- </script><script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl">
- <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}">
- <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4>
- <dl>
- <dt>Original:</dt>
- <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd>
- </dl>
- <dl class="ccu-parse">
- <dt>Change To:</dt>
- <dd>
- <input type="text" max="40" size="35" class="cc-parse-text">
- <button class="ccu-button ccu-parse">Submit</button>
- </dd>
- </dl>
- <dl class="ccu-parseverify" style="display: none;">
- <dt>Change To:</dt>
- <dd>
- <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span>
- </dd>
- <dt> </dt>
- <dd>
- <button class="ccu-button ccu-parseverify-accept">Accept</button>
- <button class="ccu-button ccu-parseverify-cancel">Cancel</button>
- </dd>
- </dl>
- </div>
- </script>
-
- </div>
-
- </div>
- </section>
- <footer>
- <div class="container">
- <div class="span-24 last FooterTop">
+ </div>
+ </section>
+ <footer>
+
+ <section class="links wrap">
+ <dl>
+ <dt>Partner With Us</dt>
+ <dd><a id="ctl00_hlFooterJobs" href="http://www.groundspeak.com/jobs.aspx">Jobs</a></dd>
+ <dd><a id="ctl00_lnkTravelAndGeotourism" href="/travel/">GeoTours & Travel</a></dd>
+ <dd><a id="ctl00_lnkBrandedPromotions" href="/brandedpromotions/">Branded Promotions</a></dd>
+ </dl>
-<div class="LocaleText">
-
- <strong>Choose Your Language:</strong>
-
-</div>
-<div class="LocaleList">
-
- <div class="selected-language">
-
- <a href="#">English▼</a>
-
- </div>
- <ul class="language-list">
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Latviešu</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, Bokmål</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li>
-
- </ul>
-
-</div>
-<script type="text/javascript">
+ <dl>
+ <dt>Legal</dt>
+ <dd><a id="ctl00_hlFooterLogo" accesskey="l" href="../about/logousage.aspx">Logo Usage Guidelines</a></dd>
+ <dd><a id="ctl00_hlFooterParksPoliceLink" href="../parksandpolice/">Parks & Police</a></dd>
+ </dl>
- jQuery(document).ready(function () {
- jQuery(".selected-language a").click(function (e) {
- e.preventDefault();
- var $loc = jQuery(this).parent().next();
- jQuery($loc).show().position({
- of: $loc.parent(),
- my: "left top",
- at: "left bottom",
- offset: "0 0",
- collision: "fit fit"
- });
- jQuery(this).addClass("Expanded");
- jQuery(document).click(function () {
- jQuery(".language-list").fadeOut("fast");
- jQuery(".selected-language a").removeClass("Expanded");
- });
- return false;
- });
- });
+ <dl>
+ <dt>Shop Geocaching</dt>
+ <dd><a id="ctl00_lnkUSAShop" href="http://shop.geocaching.com/">USA Shop</a></dd>
+ <dd><a id="ctl00_lnkInternationalShop" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></dd>
+ </dl>
+ <dl>
+ <dt>Contact Us</dt>
+ <dd><a id="ctl00_lnkHelpCenterLink" rel="external" href="http://support.groundspeak.com/index.php?pg=request">Help Center</a></dd>
+ <dd><a id="ctl00_lnkMedia" rel="document" href="../press/faq.aspx">Media Inquiries</a></dd>
+ </dl>
+ + +<div class="language-dropdown"> + <div class="LocaleText"> + Choose Language + </div> + <div class="LocaleList"> + + <div class="selected-language"> + + <a href="#">English</a> + + </div> + <ul class="language-list"> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" class="selected" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Català </a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">ÄŒeÅ¡tina</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Dansk</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Deutsch</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Ελληνικά</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Eesti</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Français</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">日本語</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">í•œêµì–´</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">LatvieÅ¡u</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Magyar</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Nederlands</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, BokmÃ¥l</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">Polski</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Português</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">РуÑÑкий</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl20_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl20$uxLocaleItem','')">Suomi</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl21_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl21$uxLocaleItem','')">Svenska</a></li> + + </ul> + + </div> +</div> +<script type="text/javascript"> + + jQuery(document).ready(function () { + jQuery(".selected-language a").click(function (e) { + e.preventDefault(); + var $loc = jQuery(this).parent().next(); + jQuery($loc).show().position({ + of: $loc.parent(), + my: "left bottom", + at: "left top-10", + collision: "fit fit" + }); + jQuery(this).addClass("Expanded"); + jQuery(document).click(function () { + jQuery(".language-list").fadeOut("fast"); + jQuery(".selected-language a").removeClass("Expanded"); + }); + return false; + }); + }); </script>
- </div>
- </div>
- <div class="container column-container">
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- About</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li>
- <li>
- <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li>
- <li>
- <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li>
- <li>
- <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Press</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li>
- <li>
- <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li>
- <li>
- <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li>
- <li>
- <a id="ctl00_hlFooterLogo" accesskey="l" title="Logo Usage Guidelines" href="../about/logousage.aspx">Logo Usage Guidelines</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Questions & Suggestions</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
- <li>
- <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
- <li>
- <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li>
- <li>
- <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Resources</strong>
+ </section>
+
+ <section class="copyright">
+ <div class="container">
+ <p>
+ © 2000-2015
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" href="../about/privacypolicy.aspx">Privacy Policy</a>
</p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li>
- <li>
- <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li>
- <li>
- <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Follow Us</strong>
- </p>
- <ul class="FooterLinks FollowUsLinks">
- <li>
- <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a></li>
- <li>
- <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a></li>
- <li>
- <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/gogeocaching/"></a></li>
- <li>
- <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a></li>
- </ul>
- </div>
- </div>
- <div class="FooterBottom">
- <div class="container">
- <p>
- Copyright
- © 2000-2013
- <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
- All Rights Reserved.
- <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
- |
- <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a>
- </p>
- </div>
+ <ul class="links-social">
+ <li>
+ <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/geocaching/"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a>
+ </li>
+ </ul>
+ </div>
+ </section>
+ </footer>
+ <div class="SkipLinks">
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
</div>
- </footer>
- <div class="SkipLinks">
- <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
- </div>
<script type="text/javascript">
//<![CDATA[
$(function() { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'Premium', null, true]); });var isLoggedIn = true;
var userDefinedCoords = {"status":"success","data":{"isUserDefined":false,"oldLatLngDisplay":"N 52° 25.504' E 009° 39.852'"}};
-cmapAdditionalWaypoints = [{"lat":52.42307,"lng":9.65038,"type":217,"name":"GC2CJPF Parking ( Parking Area )","pf":"PK"},{"lat":52.42507,"lng":9.6642,"type":218,"name":"GC2CJPF Start ( Question to Answer )","pf":"ST"},{"lat":52.4248,"lng":9.6572,"type":452,"name":"Aussichtspunkt ( Reference Point )","pf":"WO"}];
+cmapAdditionalWaypoints = [{"lat":52.42307,"lng":9.65038,"type":217,"name":"GC2CJPF Parking ( Parking Area )","pf":"PK"},{"lat":52.42507,"lng":9.6642,"type":218,"name":"GC2CJPF Start ( Virtual Stage )","pf":"ST"},{"lat":52.4248,"lng":9.6572,"type":452,"name":"Aussichtspunkt ( Reference Point )","pf":"WO"}];
mapLatLng = {"lat":52.42507,"lng":9.6642,"type":3,"name":"Kinderwald KiC"};
var ccConversions = [{"t":"Decimal","k":"DD","d":"WGS84","v":"52.425067, 009.664200"},{"t":"DDD MM SS.SSS","k":"DMS","d":"WGS84","v":"N 52° 25' 30.241\" E 009° 39' 51.120\""},{"t":"UTM","k":"UTM","d":"WGS84","v":"32U E 545164 N 5808524"}];
-var dh=false;userInfo = {ID: 4793174};
-userToken = '4OB3GFHLRR3CGMZFUAPD6CWPE24ZHP6Q7KCBEDNYY5CUNWNQIA32GZPVPFMH6IGAEYKVNNSFLMQ7BBGFDKQBT3BZGZBYKVQ4H5BWKD6MVBKYBTM627XPOUSUP6U4JF7NKKEOYJ4A6LEG2T5B6MG5AMMFOS27KNE4U2BAU4I6RAV2GHJDSEJCWVMDZN4MTGMAOEZUMRE4O275CT2QU2XAAJKVHU7RN7UA2S3OFU2TCDOZSRLJCCWA';
-includeAvatars = true;
+var dh=false;userInfo = {ID: 3409138};
+userToken = 'ID5R2NBJDBPQYVKRP2QCKFMGOD72N345U34TRF3HIUOES7I3DEYZLGMWQENANSEL75TH743VWQXA4PRVBZVB2UFIVLT5HYFG73BJY737PC6AVOROLQCJBHWZ5WOPA4ZCUMZSO7RLBORYFW5XH4FZERAO4GV6P6EU7MMIJWSXYPY4RVUTJZ7A2QJERGNUAG6CBQXBRG3YVE7KDVMMTIM2TNLSPGGQ2XGDCOXQI3X67PBO3GOHL22A';
+includeAvatars = false;
var lat=52.425067, lng=9.6642, guid='73246a5a-ebb9-4d4f-8db9-a951036f5376';
-initalLogs = {"status":"success", "data": [{"LogID":336424111,"CacheID":1811409,"LogGuid":"de243bfd-a064-4340-b520-e43d42df4019","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute bei 31 Grad im Kinderwald gewesen, da machte es auch nichts, dass die Seilfähre mit vier Kindern darauf gekentert ist !!!<br />Zwei Stunden Spaß und eine schöne Dose, alle waren zufrieden.<br />TftC stephi1972","Created":"2013-08-05","Visited":"2013-08-05","UserName":"stephi1972","MembershipLevel":3,"AccountID":3799705,"AccountGuid":"ecdbffd9-54c4-4746-b63b-1da59baace90","Email":"","AvatarImage":"9b1f5067-abb8-4e58-80fa-c179382c6c1b.jpg","GeocacheFindCount":675,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":330976044,"CacheID":1811409,"LogGuid":"118ed70d-9734-4a38-870d-a483ee83f32a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Wir waren letztes Jahr zur Brombeererntezeit schon einmal hier und haben uns ins Logbuch eingetragen, leider hat der große Cacher vergessen den Cache auch zu loggen. Da wir noch wußten wo der Cache zu finden ist, diesen erneut einen Besuch abgestattet und noch einmal eingetragen mit heutigem Datum, da das alte Datum nicht aufzutreiben war.<br /><br />Nun zum Cache, dieser macht richtig Laune für die Kinder. Wir haben bei 28 Grad die Runde in Badehose begangen. Am Besten ist das Floß, es macht so viel Spaß ins Wasser zu fallen. FÜr die kleine Cacherprinzessin kam das eher flache Wasser ein stückchen weiter in Frage und es mußten so viele Gänge und Wege begangen werden. Toll das sich um diese Anlage gekümmert wird. Immer wieder eine Fahrt wert!","Created":"2013-07-18","Visited":"2013-07-18","UserName":"NRÜ-Hunter","MembershipLevel":3,"AccountID":3132122,"AccountGuid":"263b5a96-0740-4508-ac84-63f359281e3b","Email":"","AvatarImage":"a5731207-7705-4008-a904-01ef961d56c6.jpg","GeocacheFindCount":480,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":328596370,"CacheID":1811409,"LogGuid":"5b4c8286-0b6e-4683-919f-fa60506dd843","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf der heutigen Heimreise habe ich ein wenig am Kanal und in der Nähe gefischt. Zu Beginn tat ich mich mit der Wegfindung etwas schwer, aber danach lief es wie geschmiert. Zum Glück waren keine Kinder vor Ort, da schleicht man ja nicht so gerne hinter den Bäumen rum... :-)<br />An der Seilfähre habe ich kurz gesucht, bin dann kurz drauf gestiegen und fast abgesoffen. Das wärs dann mit dem GPS-Gerät gewesen! Gerade noch einmal Glück gehabt! Ich habe mich dann aufs Prinzip Hoffnung verlassen und plante die fehlende Zahl zu erraten. Zu guter Letzt gab es dann jedoch im Listing noch zwei Möglichkeiten an die fehlende Zahl zu gelangen. Das war wirklich fair! Am Final habe ich mir dann noch einen Wolf gesucht, aber für die D-Wertung war das auch völlig in Ordnung. Hat Spaß gemacht!<br />TFTC","Created":"2013-07-09","Visited":"2013-07-09","UserName":"tripleedged","MembershipLevel":3,"AccountID":4494255,"AccountGuid":"983602a6-b99d-4888-8b07-73e0522e629a","Email":"","AvatarImage":"f0eaac0c-7d6c-46a0-9034-8e208ad5d203.jpg","GeocacheFindCount":1017,"GeocacheHideCount":4,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":325756200,"CacheID":1811409,"LogGuid":"817c38fa-99ac-425d-a692-7e3d31304a92","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schön gemachter Multi, obwohl die Wegführung nicht immer eindeutig ist. TFTC","Created":"2013-06-29","Visited":"2013-06-28","UserName":"MS Mysterio","MembershipLevel":3,"AccountID":4314909,"AccountGuid":"cb6ee233-98af-463f-a0d1-1e38941cd9b7","Email":"","AvatarImage":"","GeocacheFindCount":1883,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":324383118,"CacheID":1811409,"LogGuid":"2791ddf8-efb3-4660-aead-634cc58fbe07","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nun ja, die Runde ist cool gemacht, hat mir echt gefallen. Die Seilfähre ist allerdings mit Vorsicht zu geniessen. Bin spontan gekentert. Für die Idee lasse ich gerne auch einen FAV-Point hier.","Created":"2013-06-23","Visited":"2013-06-23","UserName":"GiSyd","MembershipLevel":3,"AccountID":2479302,"AccountGuid":"d4170df1-51ca-41e6-92a8-03d1d9fceec5","Email":"","AvatarImage":"ef3ed1c4-6795-4042-80e7-48c2ab66482c.jpg","GeocacheFindCount":363,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":319256335,"CacheID":1811409,"LogGuid":"961160af-77ce-4a9b-9b88-7febb9d222c9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nett gemachte Fragen an sehr schöner Strecke. Danke dafür! Nach kleinem Kampf mit der Seilfähre (bei dem zumindest die Zuschauer was zu lachen hatten) und Austausch mit anderen Cachern, dann das Final gefunden und geloggt.","Created":"2013-06-02","Visited":"2013-06-02","UserName":"mstig","MembershipLevel":3,"AccountID":6141473,"AccountGuid":"eb95a251-bee3-4334-b5af-1dc90a52fbd6","Email":"","AvatarImage":"ac70296c-d7dd-4245-a8c7-71f67a31dc12.png","GeocacheFindCount":212,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":319195790,"CacheID":1811409,"LogGuid":"ff742e88-3bfa-4d21-9e15-06ce4beae338","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Eine wirklich runde Sache, die den Kindern sehr gut gefallen hat!<br />Alle Aufgaben konnten gut und schnell gelöst werden und das Oberhaupt hatte das Final richtig berechnet ;-)<br />Da wir nicht ganz alleine waren, liebe Grüße an unsere Mitcacher...<br /><br />DFDC!<br /><br />IN: wir lassen gerne eine blaue Schleife da","Created":"2013-06-02","Visited":"2013-06-02","UserName":"4Brausens","MembershipLevel":3,"AccountID":6135781,"AccountGuid":"a3beb09e-0968-4cc5-9f4b-f777d67d451a","Email":"","AvatarImage":"0217d1e7-8599-4a1a-83b4-6517ec3ac80d.png","GeocacheFindCount":491,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":314374200,"CacheID":1811409,"LogGuid":"1362bfae-e4ac-4a5e-b7f9-7bbf2a923a7f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf Cachertour zusammen mit Daisy19810, Zwerge113, DerAllesfinder und unserer Schnecke diese tolle Runde angegangen und gelöst. Danke fürs Zeigen! Schleifchen in.","Created":"2013-05-14","Visited":"2013-05-09","UserName":"DrKadom","MembershipLevel":3,"AccountID":3946500,"AccountGuid":"8a77654c-6c6d-4d68-856e-43c2fa63d693","Email":"","AvatarImage":"232819b9-0cb7-4a04-bf69-032246d884c1.jpg","GeocacheFindCount":275,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":312674698,"CacheID":1811409,"LogGuid":"8fc8201d-6831-49b9-b4be-430b7c1720b0","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Unsere Himmelfahrttruppe mit Zwerge113, DerAllesfinder, DrKadom und meiner Wenigkeit zog heute durch den Mecklenheider Forst um ein paar Dosen zu suchen (und zu finden).<br />Dieser Multi ist wirklich sehr schön gemacht und für Kinder der Hit! Absolut empfehlenswert.<br />Danke, ohne diesen Cache wären wir hier sicher nie hergekommen.<br />Out: nix; In: Schleifchen","Created":"2013-05-09","Visited":"2013-05-09","UserName":"Daisy19810","MembershipLevel":3,"AccountID":6335627,"AccountGuid":"f2fa001b-5d0c-400e-8c26-97b8eb9046f5","Email":"","AvatarImage":"","GeocacheFindCount":247,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":312658002,"CacheID":1811409,"LogGuid":"5c2ea859-c3ec-45be-8f86-2d0fcd95a81c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schöner Cache im zweiten Anlauf gefunden. :-)","Created":"2013-05-09","Visited":"2013-05-09","UserName":"DerAllesfinder","MembershipLevel":1,"AccountID":4094871,"AccountGuid":"e5703e78-4b76-4d1c-b3a6-148b7f63b63f","Email":"","AvatarImage":"","GeocacheFindCount":24,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":312655849,"CacheID":1811409,"LogGuid":"fc791537-2931-4fd6-a6d2-c521b91e4f7f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Feiertag ausgenutzt um zu cachen. Mit Daisy19810 und Anhang erfolgreich gefunden :-)<br /><br />Danke","Created":"2013-05-09","Visited":"2013-05-09","UserName":"Zwerge113","MembershipLevel":1,"AccountID":4065218,"AccountGuid":"8b567e37-9d1a-459b-9e97-7583db898133","Email":"","AvatarImage":"","GeocacheFindCount":32,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":310207771,"CacheID":1811409,"LogGuid":"4445100f-a40d-4795-9592-3476f05ef09e","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Mit viel Freude und Spaß gesucht und gefunden :) Danke für diesen tollen cache","Created":"2013-05-01","Visited":"2013-05-01","UserName":"Hasiundbär","MembershipLevel":3,"AccountID":5864723,"AccountGuid":"0f859f7b-7998-49a2-bf2b-62a39cb6711b","Email":"","AvatarImage":"32c9ea1a-698c-4dc5-9012-beb9fe02bd7b.jpg","GeocacheFindCount":148,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":311648724,"CacheID":1811409,"LogGuid":"5a25441d-6cc9-4ccd-9630-d028894462a3","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Bin diese wunderschöne Runde mit meinem dreijährigen Sohn abgelaufen. So etwas hätte ich mir als kind gewünscht, eine super Anlage zum spielen. Das final hatte es ja in sich, aber nach ein wenig suchen konnten wir die Dose heben.<br />Habe einen TB da gelassen.<br />#407","Created":"2013-05-05","Visited":"2013-04-28","UserName":"theo_retisch","MembershipLevel":3,"AccountID":4149286,"AccountGuid":"7f97b3cc-f711-40ab-afa0-739b62197bca","Email":"","AvatarImage":"58cdd04d-5775-48fa-b07d-06f1f536cc15.png","GeocacheFindCount":519,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":309448901,"CacheID":1811409,"LogGuid":"4e01c66c-8025-4537-bd53-b4a7614ccc66","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute auf kleiner Fahrradrundtour das Finale gehoben. DfdC sagen ConTomi","Created":"2013-04-28","Visited":"2013-04-28","UserName":"Contomi","MembershipLevel":3,"AccountID":5250924,"AccountGuid":"ca00ad98-5333-43d6-a699-c8fc7c237d0e","Email":"","AvatarImage":"bec482ce-1873-48c5-a8b0-6b32d90cc9ad.jpg","GeocacheFindCount":158,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":309430772,"CacheID":1811409,"LogGuid":"a8874f36-0584-49f5-b075-dd7e73b53338","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schön ausgearbeiteter Cache! Wenn es hier richtig warm ist, dann wird es sicher nur so von Muggel-Hobbits wimmeln. Heute war es noch ruhig.<br />TB out","Created":"2013-04-28","Visited":"2013-04-28","UserName":"Erdmaennchen_3","MembershipLevel":3,"AccountID":3802800,"AccountGuid":"c6cb1fda-ee42-4100-90b1-d750467d4657","Email":"","AvatarImage":"df6c91db-76b1-434b-b847-0a40fa791453.jpg","GeocacheFindCount":1617,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":307621702,"CacheID":1811409,"LogGuid":"5ed01148-9d41-4cdd-9769-4f097d7c8b1c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"diese Cache ist wirklich süß gemacht.dfdc","Created":"2013-04-21","Visited":"2013-04-21","UserName":"Die 3 Geonauten","MembershipLevel":1,"AccountID":5600675,"AccountGuid":"53074204-5648-4ea0-9665-e54fb2697c0d","Email":"","AvatarImage":"","GeocacheFindCount":37,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":307183303,"CacheID":1811409,"LogGuid":"1c86c4f9-3798-4091-afce-b7d010732db6","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Sehr schön gemachter Kindercache!<br />Danke dafür! \t<img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" />","Created":"2013-04-20","Visited":"2013-04-20","UserName":"HorstHorstmann","MembershipLevel":1,"AccountID":6518802,"AccountGuid":"9415565a-8035-42cd-b448-e89a60d22fb9","Email":"","AvatarImage":"","GeocacheFindCount":15,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":300774617,"CacheID":1811409,"LogGuid":"5ae17e51-fbfa-4049-b9b3-cb2dbcdc92a5","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"sehr schöner Cache. Leider war die Fähre nicht da doch dank des Tipps haben wir das Ziel doch gefunden.","Created":"2013-03-26","Visited":"2013-03-26","UserName":"TeamLeo00","MembershipLevel":3,"AccountID":5502709,"AccountGuid":"372916b2-a76d-4393-a831-d398cba13b71","Email":"","AvatarImage":"b0c9e3af-1785-4430-bb88-c80134d02684.jpg","GeocacheFindCount":108,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":297431085,"CacheID":1811409,"LogGuid":"2c80abd0-d7de-4eeb-aba2-5e3d2c58ecb0","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auch wenn es zum Baden eindeutig noch zu kalt war, habe ich den Cache gut gefunden","Created":"2013-03-08","Visited":"2013-03-08","UserName":"loenni","MembershipLevel":3,"AccountID":4860261,"AccountGuid":"2df93c3f-982d-43fe-8b91-165bf2e3abf5","Email":"","AvatarImage":"","GeocacheFindCount":2515,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":297134777,"CacheID":1811409,"LogGuid":"0c6319f6-591d-42c6-b397-88e67447fe72","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf \"after-work-tour\" diesen Multi als NC absolviert. Alle Stationen konnten im Team mit Axel-Foley gut gefunden werden. Vielen Dank!","Created":"2013-03-06","Visited":"2013-03-05","UserName":"Nilleboy","MembershipLevel":3,"AccountID":1221755,"AccountGuid":"d038670b-5689-420e-950a-4d40967c9e64","Email":"","AvatarImage":"702eebc3-525e-46ae-ba95-a89b69b325fb.jpg","GeocacheFindCount":4758,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":297117378,"CacheID":1811409,"LogGuid":"63b794b8-e4bd-410e-b1d1-5a7a46357f62","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf kleiner Cacherunde am Abend im Team mit Nilleboy auch diesen Multi durchlaufen. <br />TFTC","Created":"2013-03-05","Visited":"2013-03-05","UserName":"Axel-Foley","MembershipLevel":3,"AccountID":1836934,"AccountGuid":"342fa7de-405c-4d1c-b104-79c8d59ffb46","Email":"","AvatarImage":"83f5a949-9f61-4ac8-bc4f-f93630c0135c.jpg","GeocacheFindCount":6426,"GeocacheHideCount":36,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":296501698,"CacheID":1811409,"LogGuid":"1e66c165-d70d-4783-ab65-c9db73a24882","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"#2283: Das war eine schöne Runde. Vom angegebenen Parkplatz aus sind wir die Stationen in umgekehrter Reihenfolge abgelaufen. So konnten wir auf dem Rückweg zum Cachemobil die anderen Stationen des Kinderwaldes erkunden. Für Cacher mit Kindern ist dieset Cache ein Muss.<br />Dafür gibt's einen FP.<br />DFDC <b><font color=\"blue\">mue-th</font></b><font color=\"blue\"></font>","Created":"2013-03-03","Visited":"2013-03-03","UserName":"mue-th","MembershipLevel":3,"AccountID":2601691,"AccountGuid":"473ce8cb-c95a-445c-805f-58e3c5442829","Email":"","AvatarImage":"a1a1d0fc-d54d-46f5-b2de-1b6149b7c234.jpg","GeocacheFindCount":2877,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":295044129,"CacheID":1811409,"LogGuid":"4cc3171f-1f0f-49c9-a0fd-30bb93a0945a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Es war sehr schon cach. <br />DFDC","Created":"2013-02-22","Visited":"2013-02-22","UserName":"nekolny","MembershipLevel":1,"AccountID":2018515,"AccountGuid":"ff452d34-4f18-4c2e-bce4-f11d2e65d056","Email":"","AvatarImage":"","GeocacheFindCount":163,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":294890152,"CacheID":1811409,"LogGuid":"3bb18a57-1986-4ee7-a4c4-83fbb6a9af01","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Bei der momentanen Kälte und den angedrohten Niederschlägen legten wir die heutige Runde ein wenig in den Wald. Das schützte ganz gut vor dem kalten Wind, und der zeitweise fallende Schneeregen wurde auch ein wenig gedämpft. So konnten wir diese schöne Runde ganz gut geniessen. Nur für die Badehose war heute definitiv nicht die geeignete Jahreszeit <img src=\"/images/icons/icon_smile_wink.gif\" border=\"0\" align=\"middle\" /><br />Schliesslich hatten wir alles beisammen, um die Dose gut finden zu können. <br />Vielen Dank für diese schöne Tour!","Created":"2013-02-20","Visited":"2013-01-27","UserName":"fafafafa","MembershipLevel":3,"AccountID":3536809,"AccountGuid":"8df66947-094c-42d9-a48c-cbb65732d7bd","Email":"","AvatarImage":"08b32861-980a-4e9d-ab58-8fe95549e1a5.jpg","GeocacheFindCount":2221,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":291273728,"CacheID":1811409,"LogGuid":"e0fade10-d897-4387-9f36-cc7da4a8c360","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Dieser Cache im Kinderwald hat uns sehr gut gefallen.Vielen Dank fürs Zeigen sagt Immergruen61","Created":"2013-01-28","Visited":"2013-01-27","UserName":"Immergruen61","MembershipLevel":1,"AccountID":3510044,"AccountGuid":"bb127b72-e5d0-408f-be49-550ed59e8270","Email":"","AvatarImage":"","GeocacheFindCount":432,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 171, "rows": 171 } };
-var gaToken = 'UA-2020240-1';//]]>
+initalLogs = {"status":"success", "data": [{"LogID":476003048,"CacheID":1811409,"LogGuid":"6daf80b4-3219-4862-b527-4967f57defad","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Needs Maintenance","LogTypeImage":"45.png","LogText":"Bitte die Berechnung für A ändern","Created":"2015-02-08","Visited":"2015-02-08","UserName":"Nicolix","MembershipLevel":3,"AccountID":2896084,"AccountGuid":"50edc314-d601-480e-8c6a-c096c11db598","Email":"","AvatarImage":"e1537018-d686-42e9-bac9-e911f46593f8.png","GeocacheFindCount":2230,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":476000835,"CacheID":1811409,"LogGuid":"969371df-2eab-4275-8243-9b7b8bdeeed7","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Diesen Multi gingen nessi09 und ich heute auf unserer Cachingtour gemeinsam an. Am Start angekommen mussten wir zwei Sachen feststellen: Keine Räder und keine Punkte! Die Räder waren schnell angeschlossen, doch die Echse scheint erst kürzlich gestrichen worden zu sein, wobei sie wohl ihre außergewöhnliche Schuppenfarbe verloren hat. Schade. Die nächsten Stationen konnten wir gut finden und die Aufgaben gut lösen, doch dann der nächste \"Schock\", keine Seilfähre. Doch da wir A ganz gut raten konnten, war die Berechnung dann kein Problem mehr und wir konnten uns bald darauf ins Logbuch eintragen. Vielen Dank für diesen netten Multi, der mir viel Spaß gemacht hat!","Created":"2015-02-08","Visited":"2015-02-08","UserName":"Nicolix","MembershipLevel":3,"AccountID":2896084,"AccountGuid":"50edc314-d601-480e-8c6a-c096c11db598","Email":"","AvatarImage":"e1537018-d686-42e9-bac9-e911f46593f8.png","GeocacheFindCount":2230,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[{"ImageID":26244411,"ImageGuid":"f12407de-4158-475e-be28-d244f260ba9e","Name":"Keine Räder","Descr":"","FileName":"f12407de-4158-475e-be28-d244f260ba9e.jpg","Created":"2015-02-08","LogID":476000835,"CacheID":1811409,"ImageUrl":null},{"ImageID":26244438,"ImageGuid":"a2fcad6b-6a83-44fd-8f51-da439fd269c4","Name":"Keine Punkte","Descr":"","FileName":"a2fcad6b-6a83-44fd-8f51-da439fd269c4.jpg","Created":"2015-02-08","LogID":476000835,"CacheID":1811409,"ImageUrl":null},{"ImageID":26244456,"ImageGuid":"2ccb05da-7cc3-44d4-9ca1-2053ba6dcbd7","Name":"Keine Seilfähre","Descr":"","FileName":"2ccb05da-7cc3-44d4-9ca1-2053ba6dcbd7.jpg","Created":"2015-02-08","LogID":476000835,"CacheID":1811409,"ImageUrl":null}]},{"LogID":462798806,"CacheID":1811409,"LogGuid":"32f21349-6fda-407a-8560-bc8ee873ecfc","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Wow, toller Cache! Vielen Dank für den schönen Familiennachmittag!","Created":"2014-11-23","Visited":"2014-11-23","UserName":"NiedersachsenFee","MembershipLevel":1,"AccountID":7350639,"AccountGuid":"480d7529-30bd-4171-97cc-dca3985733ae","Email":"","AvatarImage":"","GeocacheFindCount":66,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":452401275,"CacheID":1811409,"LogGuid":"aede63cb-3552-4cac-a087-6cafaf8c006f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Das war mal einer für die Co. Es heißt ja, von Nachwuchs-Cachern für Nachwuchs-Cacher.<br /><br />Dfdc","Created":"2014-10-11","Visited":"2014-10-11","UserName":"Eilie und Co","MembershipLevel":3,"AccountID":1182877,"AccountGuid":"db0bc9a1-bdd7-4f4b-8b85-ab9a4db26c86","Email":"","AvatarImage":"a74daf4e-1fd0-460a-8000-4fdeda06278d.jpg","GeocacheFindCount":386,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":451787207,"CacheID":1811409,"LogGuid":"ff6e5a3d-bb0a-43c9-a2ad-3db760618a8f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hier konnte ich nicht alle variablen ermitteln. Durch die Quersumme und gleichsetzen konnte ich dann aber die beiden fehlenden variablen ermitteln und dann die eher für kleine Leute geeignete Finaldose finden. <br />TFTC","Created":"2014-10-08","Visited":"2014-10-08","UserName":"Sheglo","MembershipLevel":3,"AccountID":8993236,"AccountGuid":"5edd9a04-2450-4ac1-93be-3f7d387d8920","Email":"","AvatarImage":"","GeocacheFindCount":857,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":448109769,"CacheID":1811409,"LogGuid":"b22e3cdc-af61-4e1a-a7a4-5f811c14932b","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Trotz drohender Wolken habe ich mich heute Nachmittag auf in den Mecklenheider Forst gemacht. Alles habe ich zwar nicht entdecken können, aber mit etwas Kombinieren erhielt ich plausible KOs, die auch stimmten. Und so konnte ich mich dann ganz ungestört im Logbuch verewigen. Vielen Dank für die schöne Runde und<br /><br />--- T4TC ---","Created":"2014-09-25","Visited":"2014-09-25","UserName":"DeLaTrick","MembershipLevel":3,"AccountID":3696982,"AccountGuid":"44cfcd2c-d3f9-49b8-828a-9f692939f7ab","Email":"","AvatarImage":"9aeb67b2-40e5-4532-8443-312222cd0e4f.jpg","GeocacheFindCount":7068,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":443692327,"CacheID":1811409,"LogGuid":"bcba0a3e-d021-42a5-bfc3-ca0b2fa402c2","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"heute mit einer gruppe Kindern gefunden. Passt beim Schiff auf schaukelnde Kinder können leicht nass werden. sonst Super cach aufjeden fall für die kinder.","Created":"2014-09-08","Visited":"2014-09-08","UserName":"_locke92_","MembershipLevel":1,"AccountID":4940486,"AccountGuid":"7d379893-a44b-4c8b-ac71-b1c2179bc664","Email":"","AvatarImage":"","GeocacheFindCount":30,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":445922654,"CacheID":1811409,"LogGuid":"7bb33d63-fa68-4c13-bb34-3ae62a9c6819","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Danke für den Cache!","Created":"2014-09-16","Visited":"2014-08-17","UserName":"moonbyte","MembershipLevel":1,"AccountID":7826922,"AccountGuid":"17cec138-e064-42dc-b66d-4c4a6d17ec4a","Email":"","AvatarImage":"3b23fe74-aa6c-4edb-a154-3d7d4335bd5e.jpg","GeocacheFindCount":223,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":436986872,"CacheID":1811409,"LogGuid":"1ec99a48-4b25-4080-922c-346a55381079","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Danke für den schönen Multi, er hat sehr viel Spaß gemacht.","Created":"2014-08-19","Visited":"2014-08-17","UserName":"Cocoskatze","MembershipLevel":3,"AccountID":6844532,"AccountGuid":"5387dfd1-7fec-48d5-be99-2f4f17483972","Email":"","AvatarImage":"4ed8751b-62ba-440b-b763-35ff4239c755.jpg","GeocacheFindCount":227,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":434503977,"CacheID":1811409,"LogGuid":"f9641358-4741-42aa-8ece-628da69674ac","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Eine wirklich schöne Gegend für die Kinder, sie wollten gar nicht mehr weg. Leider sind die Aufgaben teils schwer zulösen, da sie der Zerstörungswut anheimgefallen sind, aber dank der Quersumme haben wir das Rätsel lösen können.<br /><br />Lieben Dank für den Cache","Created":"2014-08-13","Visited":"2014-08-13","UserName":"HappyFamily*","MembershipLevel":3,"AccountID":5829133,"AccountGuid":"40b4616d-d3b8-453b-b218-ebced58c0ce7","Email":"","AvatarImage":"","GeocacheFindCount":21,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":412877556,"CacheID":1811409,"LogGuid":"a8a87d80-3da6-42d2-bec2-7a5243f7d8a6","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"mit der bratenbande gefunden<br />dfdc<br />schulz und schulze","Created":"2014-06-02","Visited":"2014-06-01","UserName":"schulz und schulze","MembershipLevel":1,"AccountID":1417620,"AccountGuid":"be15a8e5-33ea-4151-a9f6-775f49ef5328","Email":"","AvatarImage":"1ba3d006-6943-4d82-802e-7c46691af36b.jpg","GeocacheFindCount":1470,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":412634896,"CacheID":1811409,"LogGuid":"8af367ac-e34a-4486-bba2-fdf03b294624","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"mit schulz und schulze dem kinderwald mal wieder einen besuch abgestattet und die dose gefunden<br />dfdc<br />bratenbande","Created":"2014-06-01","Visited":"2014-06-01","UserName":"bratenbande","MembershipLevel":3,"AccountID":1070679,"AccountGuid":"b32cea93-c547-494a-9d9a-520ba01909d3","Email":"","AvatarImage":"57709ef5-8af2-4f7e-8e61-6082be637c7f.jpg","GeocacheFindCount":4300,"GeocacheHideCount":16,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":411253228,"CacheID":1811409,"LogGuid":"41fab16f-bbfb-4849-844b-bc2611a72a99","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Eine tolle Runde am Vater Tag. Danke für den tollen cache! Aerdna71 und Ajnif 88","Created":"2014-05-29","Visited":"2014-05-29","UserName":"aerdna71","MembershipLevel":3,"AccountID":7862919,"AccountGuid":"65583307-a685-4432-bc48-b6a70658d709","Email":"","AvatarImage":"","GeocacheFindCount":1185,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":416157417,"CacheID":1811409,"LogGuid":"fadfdb5f-3c71-48d8-9831-b6c1b5c98af3","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nach einem unfreiwilligen Tauchgang mit Padddi bei diesem tollen Wetter war dieser \"ErlebnisCache\" gut zu finden und hat auch noch unheimlich Spaß gemacht.","Created":"2014-06-14","Visited":"2014-05-25","UserName":"LovelessKitten","MembershipLevel":1,"AccountID":7457179,"AccountGuid":"ed7d4899-51f3-4b95-ab00-6dbd0906777a","Email":"","AvatarImage":"1a47f12c-0974-4a9f-88ca-2eca23e1e9a3.gif","GeocacheFindCount":184,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":410010095,"CacheID":1811409,"LogGuid":"7879928e-c25a-464a-99b6-124e53a35eef","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"DIeser Cache hat wirklich sehr viel Spaß gemacht und war in schöner Umgebung. Als wir denn die Seilfähre testen wollten, haben ich und LovelessKitten nasse Füße bekommen. Aber es war ja so warm das das sogar relativ angenehm war. Vielen Dank","Created":"2014-05-25","Visited":"2014-05-25","UserName":"Padddi","MembershipLevel":1,"AccountID":7437121,"AccountGuid":"f6147e5c-416c-4bb2-a3b8-f2575e78c4ad","Email":"","AvatarImage":"dc7adc55-12b4-473a-8dae-9971abe258c9.jpg","GeocacheFindCount":191,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":403600129,"CacheID":1811409,"LogGuid":"97cd5319-b968-4343-9ec5-03394db94921","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Wir haben ihn.....Hat sehr viel Spaß gemacht. ....","Created":"2014-05-03","Visited":"2014-05-02","UserName":"Team Twins07","MembershipLevel":1,"AccountID":9409323,"AccountGuid":"a2e25fd9-7366-4a22-9586-caa02d4c5321","Email":"","AvatarImage":"","GeocacheFindCount":1,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[{"ImageID":22187997,"ImageGuid":"916c25f5-7d7e-4e50-a458-419ef0a4e77c","Name":"20140502_173902","Descr":"","FileName":"916c25f5-7d7e-4e50-a458-419ef0a4e77c.jpg","Created":"2014-05-03","LogID":403600129,"CacheID":1811409,"ImageUrl":null}]},{"LogID":402752947,"CacheID":1811409,"LogGuid":"c1c56e5f-deb3-4114-9e43-34798f92225a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Write note","LogTypeImage":"4.png","LogText":"TB in.","Created":"2014-04-30","Visited":"2014-04-30","UserName":"blafoo","MembershipLevel":3,"AccountID":1912314,"AccountGuid":"0564a940-8311-40ee-8e76-7e91b2cf6284","Email":"","AvatarImage":"816ea7ab-8878-4e22-8097-ba18294ac8d9.png","GeocacheFindCount":1312,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":401272415,"CacheID":1811409,"LogGuid":"e89b9622-f532-428b-bde2-f525e49808c6","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Erst dachte ich ui ganz schön lang, aber war doch nicht so schlimm. Die Stationen haben Spaß gemacht, beim Final musste ein wenig länger gesucht werden. TFTC","Created":"2014-04-26","Visited":"2014-04-26","UserName":"Enyea","MembershipLevel":3,"AccountID":2962113,"AccountGuid":"ade3f2ed-83e1-4115-a02e-58242bd190ba","Email":"","AvatarImage":"9bcd4d5f-e1ac-4712-8486-ec10e1f84b7d.jpg","GeocacheFindCount":4390,"GeocacheHideCount":16,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":400302961,"CacheID":1811409,"LogGuid":"974e7902-4729-433f-9b38-ae592960c93c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute nach einigen schwierigkeiten doch noch gefunden. \"dem weg in nördliche richtung folgen\" ist aber auch ein falscher freund xD","Created":"2014-04-22","Visited":"2014-04-22","UserName":"ermd2","MembershipLevel":3,"AccountID":7163462,"AccountGuid":"54ee8ceb-8e0b-4ef9-b941-d11d9eddbef1","Email":"","AvatarImage":"b0ddf3d7-58b8-4d03-9cc9-e69c3bfba8a2.jpg","GeocacheFindCount":137,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":408518056,"CacheID":1811409,"LogGuid":"43f11ea8-e005-4083-9bd3-fc8a9688371a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zusammen mit baldi durch den Kinderwald. Bis auf eine Station alles prima gefunden. Danke für die nette Runde.<br />Kunterbunt","Created":"2014-05-19","Visited":"2014-04-06","UserName":"kunterbunt","MembershipLevel":3,"AccountID":1050708,"AccountGuid":"096316ae-7804-4f63-981e-87a028f1dda8","Email":"","AvatarImage":"4e95a982-31fa-41dc-8d5a-9d8ca9ab37a0.jpg","GeocacheFindCount":1698,"GeocacheHideCount":4,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":407381811,"CacheID":1811409,"LogGuid":"f99d5df4-eac5-441f-af4c-31e118f705a5","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Kleine Erkundungstour mit kunterbunt.<br /><br />Leider war die Seilfaehre nicht da. An der naechsten Station dann Muggles.<br /><br />Das Finale konnten wir trotzdem finden.<br /><br />Danke fuer den Cache<br /><br />baldi","Created":"2014-05-15","Visited":"2014-04-06","UserName":"baldi","MembershipLevel":3,"AccountID":565190,"AccountGuid":"a9710d10-99c2-4c4e-97ca-5c5e3aedaebf","Email":"","AvatarImage":"","GeocacheFindCount":3055,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":390148964,"CacheID":1811409,"LogGuid":"1ef5171b-3346-4928-9cdf-657cf5c6f181","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Eine schöne Runde...nach kurzer Zeit konnte die Dose gefunden werden.<br />DFDC / CaDi","Created":"2014-03-21","Visited":"2014-03-21","UserName":"derek78","MembershipLevel":3,"AccountID":2365504,"AccountGuid":"c3f49617-12e7-423c-9f72-a66bbbc031cf","Email":"","AvatarImage":"a8ecb3ee-f5cf-4015-b186-a96c7dbaed4a.jpg","GeocacheFindCount":4923,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":388678520,"CacheID":1811409,"LogGuid":"8f31369b-a5e8-4dee-83fc-ebe9dd15e9bc","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"im Team mit The Chaos Family schnell gefunden und geloggt","Created":"2014-03-15","Visited":"2014-03-09","UserName":"LüLei2014","MembershipLevel":1,"AccountID":8019634,"AccountGuid":"0c7fae0b-f471-48a4-b70f-9d6a966f7987","Email":"","AvatarImage":"","GeocacheFindCount":4,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":387323524,"CacheID":1811409,"LogGuid":"d7f989bb-c44a-40ac-969b-8d9b8744e01d","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"So dies war der heutige Abschluss unsere Kinder hatten tierisch Spaß leider war die Seilfähre nicht da schade","Created":"2014-03-09","Visited":"2014-03-09","UserName":"The Chaos Family","MembershipLevel":3,"AccountID":7626789,"AccountGuid":"293958d3-c49d-423f-ae15-79a098ba6f55","Email":"","AvatarImage":"5638409b-df2c-4e34-bd26-97c70a5714e8.jpg","GeocacheFindCount":1084,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":387252010,"CacheID":1811409,"LogGuid":"cf0ade9c-36f2-494f-842e-c517750e7b06","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Diesen Cache haben wir heute als Vorbereitung für ein Event mit einigen Kindern am nächsten Wochenende \"getestet\" und für gut befunden. Wir werden nächste Woche wieder kommen und den Cache dann mit den Kindern machen. DfdC!","Created":"2014-03-09","Visited":"2014-03-09","UserName":"SordChian","MembershipLevel":1,"AccountID":3876908,"AccountGuid":"7726406e-0682-409a-8c60-71c2a0105bc1","Email":"","AvatarImage":"a02ba54c-2eb9-4499-9ea5-18a81d99a50e.jpg","GeocacheFindCount":64,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 218, "rows": 218 } };
+var gaToken = 'UA-2020240-1';ga('create', 'UA-2020240-35', 'geocaching.com'); ga('send', 'pageview');//]]>
</script>
</form>
- <script type="text/javascript">
+ <script src="/js/jquery_plugins/tinynav.min.js"></script>
+ <script src="/js/matchMedia.js"></script>
+ <script src="/account/scripts/custom/message-center-header-widget.js"></script>
+ <script>
+ $('#messagecenterheaderwidget').messageCenterHeaderWidget();
+
var browserType = {
IE: !!(window.attachEvent && !window.opera),
Opera: !!window.opera,
@@ -1537,18 +1392,57 @@ var gaToken = 'UA-2020240-1';//]]> MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};
+ // Modernizr only identifies browsers that support touch events; Windows Phone and webOS handle touch differently
+ var isMobile = (/(webOS|hpwOS|IEMobile)/).test(navigator.userAgent);
+
$(function () {
- // Make the menu system play nice with all browsers:
- $('ul.Menu li').hover(function () {
- $(this).addClass('hover');
- $('ul:first', this).css('visibility', 'visible');
- }, function () {
- $(this).removeClass('hover');
- $('ul:first', this).css('visibility', 'hidden');
+ var $topMenuLinks = $('.Menu > li');
+
+ $topMenuLinks.children('a').each(function () {
+ $(this).on('touchstart click', function (e) {
+ e.stopPropagation();
+
+ var $this = $(this),
+ $parent = $(this).parent();
+
+ $topMenuLinks.removeClass('hover');
+
+ if (!$parent.hasClass('hover') && $this.hasClass('Dropdown')) {
+ e.preventDefault();
+ $parent.addClass('hover');
+ }
+ });
+ });
+
+ var $userMenuBtn = $('.logged-in-user .li-user-toggle');
+
+ $userMenuBtn.on('touchstart click', function (e) {
+ e.stopPropagation();
+ $(this).next('ul').addClass('user-expanded');
+ });
+
+ $(document).on('click', function (e) {
+ if ($('.user-expanded').length && !$(e.target).parents().hasClass("user-expanded")) {
+ $('.user-expanded').removeClass("user-expanded");
+ }
+ if (!$(e.target).parents().hasClass("Menu")) {
+ $topMenuLinks.removeClass("hover");
+ }
});
- if (!isiOS()) {
- // Constructing a Twitter-esque Login:
- $(".SignInLink").click(function (e) {
+
+ if (isMobile || Modernizr.touch) {
+ // Convert language dropdown to native select
+ $("ul.language-list .selected").parent().addClass("selected");
+ $(".selected-language a, ul.language-list").hide();
+ $(".language-list").tinyNav({
+ active: 'selected'
+ });
+ }
+
+
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").on('click', function (e) {
+ if (window.matchMedia("(min-width: 1000px)").matches) {
e.preventDefault();
$("#SignInWidget").toggle();
$(".ProfileWidget").toggleClass("WidgetOpen");
@@ -1561,21 +1455,14 @@ var gaToken = 'UA-2020240-1';//]]> }
});
return false;
- });
- }
+ }
+ });
+
if (!("placeholder" in document.createElement("input"))) {
$("#SignInWidget label").removeClass("hideMe");
}
- $('.SignedInProfileLink').truncate({
- width: 120,
- after: '&hellip;',
- center: false,
- addclass: false,
- addtitle: false
- });
-
// Hide the warning message if the user closed it already
if ($.cookie('hide_warning') != null) {
$(".WarningMessage").hide();
@@ -1588,739 +1475,735 @@ var gaToken = 'UA-2020240-1';//]]> function isiOS() {
return (
- (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
- );
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
}
});
</script>
-
- <script type="text/javascript">
- <!--
-
- function s2gps(guid) {
- var w = window.open('/seek/sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no');
- w.focus();
- }
-
- function s2phone(wpid) {
- window.location.href='/seek/sendtophone.aspx?gc=' + wpid;
- }
-
- function pl(lc) {
- document.location.href='/seek/cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n');
- }
-
- function setNotification(id) {
- //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'});
- //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'});
- }
-
- function cmo(id) {
- Cookie.set('sn', true);
- }
-
- function pp(img) {
- var w = window.open(img);
- w.focus();
- }
-
- var map, bounds;
- var canUpdateFavoriteStatus = true;
- var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false;
- var logInitialLoaded = false;
- var $tfoot = $("#cache_logs_table").find("tfoot");
- var currentPageIdx = 1, totalPages = 1, pageSize = 10;
- var isBusy = false;
-
- var locString = {
- decrypt: 'Decrypt',
- encrypt: 'Encrypt'
- };
-
- $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle");
- $("#tmpl_CacheLogImages").template("tmplCacheLogImages");
- $("#tmpl_CacheLogRow").template("tmplCacheLogRow");
-
- $(".EncryptDecrypt")
- .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} })
- .click(function (e) {
- e.preventDefault();
- $("tr.log-row").each(function (i, obj) {
- var $obj = $(obj);
- if ($obj.data("encoded") == true) {
- var lt = $obj.find("p.LogText");
- //var ltDecoded = $('<div />').html(lt.html()).text();
- lt.html(convertROTStringWithBrackets(lt.html()));
- }
- });
-
- decryptLogs = !decryptLogs;
-
- $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
-
- return false;
- });
-
- function appendNewLogs(obj) {
-
- totalPages = obj.pageInfo.totalPages;
-
- var $newBody = $(document.createElement("TBODY"));
-
- $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody);
-
- $newBody.find("a.tb_images").each(function()
- {
- var $this = $(this);
- $this.fancybox({
- 'type': 'image',
- 'titlePosition': 'inside',
- 'padding': 10,
- titleFormat: function() { return $this.data('title'); }
- });
- });
-
- $("#cache_logs_table")
- .append($newBody.children());
-
- currentPageIdx = obj.pageInfo.idx + 1;
- pageSize = obj.pageInfo.size;
- }
-
- var showScroll = false;
+ + <script type="text/javascript"> + <!-- + + function s2gps(guid) { + var w = window.open('/seek/sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no'); + w.focus(); + } + + function s2phone(wpid) { + window.location.href='/seek/sendtophone.aspx?gc=' + wpid; + } + + function pl(lc) { + document.location.href='/seek/cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n'); + } + + function setNotification(id) { + //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'}); + //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'}); + } + + function cmo(id) { + Cookie.set('sn', true); + } + + function pp(img) { + var w = window.open(img); + w.focus(); + } + + var map, bounds; + var canUpdateFavoriteStatus = true; + var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false; + var logInitialLoaded = false; + var $tfoot = $("#cache_logs_table").find("tfoot"); + var currentPageIdx = 1, totalPages = 1, pageSize = 10; + var isBusy = false; + + var locString = { + decrypt: 'Decrypt', + encrypt: 'Encrypt' + }; + + $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle"); + $("#tmpl_CacheLogImages").template("tmplCacheLogImages"); + $("#tmpl_CacheLogRow").template("tmplCacheLogRow"); + + $(".EncryptDecrypt") + .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} }) + .click(function (e) { + e.preventDefault(); + $("tr.log-row").each(function (i, obj) { + var $obj = $(obj); + if ($obj.data("encoded") == true) { + var lt = $obj.find("p.LogText"); + //var ltDecoded = $('<div />').html(lt.html()).text(); + lt.html(convertROTStringWithBrackets(lt.html())); + } + }); + + decryptLogs = !decryptLogs; + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + return false; + }); + + function appendNewLogs(obj) { + + totalPages = obj.pageInfo.totalPages; + + var $newBody = $(document.createElement("TBODY")); + + $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody); + + $newBody.find("a.tb_images").each(function() + { + var $this = $(this); + $this.fancybox({ + 'type': 'image', + 'titlePosition': 'inside', + 'padding': 10, + titleFormat: function() { return $this.data('title'); } + }); + }); + + $("#cache_logs_table") + .append($newBody.children()); + + currentPageIdx = obj.pageInfo.idx + 1; + pageSize = obj.pageInfo.size; + } + + var showScroll = false; + + function callLogLoad(hideFooter) { + if (screen.width > 1090){ + showScroll = true; + } + $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs }, + function (response) { + if (response.status == "success") { + appendNewLogs(response); + if( hideFooter || (totalPages < currentPageIdx) ) { + $tfoot.hide(); + } + } else if (response.status == "error" && response.value == "1") { + // reload the page since the data had expired. + window.location.reload(); + } + isBusy = false; + }); + } + + $("#add_to_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv++; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr--; + $(".favorite-rank").text(fr); + + $("#pnlNonfavoriteCache").fadeOut("fast", function () { + $("#pnlFavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $("#remove_from_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv--; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr++; + $(".favorite-rank").text(fr); + + $("#pnlFavoriteCache").fadeOut("fast", function () { + $("#pnlNonfavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $(function () { + + // CSP Section + if ($("#cspMessage").length) { + + var editLink = $('a[href*="report.aspx"]').attr('href'); + + $("#cspMessage").prepend('<P><strong>Already submitted this geocache?</strong> Please check below for the Reviewer’s notes and make any necessary changes before you resubmit. You can also respond by clicking "Log Your Visit" and posting a Reviewer Note.</P>'); + $("#cspMessage").prepend('<P>Your geocache has not been published. Once your geocache is in place and all of the details have been entered, click "Submit for Review". A volunteer reviewer will begin the review process within about 7 days.</P>'); + + $("#cspGoBack").click(function (e) { + e.preventDefault(); + window.location = editLink; + return false; + }); + + $("#cspSubmit").click(function (e) { + e.preventDefault(); + $.pageMethod("/seek/cache_details.aspx/EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + window.location = '/seek/cache_details.aspx?guid=' + r.guid; + } else { + alert("There was an error enabling your cache."); + } + }); + return false; + }); + + + } + + + //override coords + if (typeof(userDefinedCoords) != "undefined") { + if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + $("#uxLatLon") + .data("isOverridden", true) + .addClass("myLatLon"); + } else if (userDefinedCoords.status == "success") { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + } else { + $("#uxLatLonLink").contents().unwrap(); + } + } else { + $("#uxLatLonLink").contents().unwrap(); + } + + + var cacheNoteText = { + DefaultText: 'Click to enter a note', + ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.', + SavingText: 'Please wait, saving your note...' + }; + + + + $("time.timeago").timeago(); + + $(".button").button(); + + var sn = Cookie.get('sn'); + + if ($('#trNotPM').length > 0) { + $('#trNotPM').toggle(!sn); + } + + $("#cache_note").editInPlace({ + callback: function (unused, enteredText) { + var me = $(this); + + var et = $.trim(enteredText); + if (et.length > 500 ) { + et = et.substr(0, 500); + } + $.pageMethod("/seek/cache_details.aspx/SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + if ($.trim(r.note) == "") { + $("#cache_note").text(cacheNoteText.DefaultText); + } else { + $("#cache_note").text(r.note); + } + + me.effect('highlight', { color: '#ffb84c' }, 'slow'); + } else { + alert(cacheNoteText.ErrorInSaving); + $("#cache_note").text(cacheNoteText.DefaultText); + } + + }); + + return cacheNoteText.SavingText; + } + , default_text: cacheNoteText.DefaultText + , field_type: "textarea" + , textarea_rows: "7" + , textarea_cols: "65" + , show_buttons: true + , bg_over: "#dad7cb" + //, callback_skip_dom_reset: true + + }); + + $("#lnk_slippyMap").click(function(e) { + e.preventDefault(); + loadDynamicMap(); + return false; + }); + + $(".inplace_field").live("focus", function () { + if ($(this).data("created") == null) { + $(this).data("created", true) + $(this).countable({ + maxLength: 500 + }); + } + }); + + $("#pcn_help").qtip({ + content: 'Enter your own notes here. No other user will be able to access them.', + position: { + my: 'top center', + at: 'bottom center' + }, + style: { + classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip' + }, + }); + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + if ($("#cache_logs_container").length > 0) { + + appendNewLogs(initalLogs); + + if (DetectMobileQuick()) { + $("#pnlButtonLoad") + .show() + .find("a.MobileButton") + .click(function (e) { + e.preventDefault(); + callLogLoad(false); + return false; + }) + .button(); + if(!DetectTierTablet()){ + $("a.MobileButton").addClass("Phone"); + } + } else { + $("#pnlLazyLoad").show(); + + $(window).endlessScroll({ + fireOnce: true, + fireDelay: 500, + bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50, + ceaseFire: function(){ + // stop the scrolling if the last page is reached. + return (isLoggedIn == false) || (totalPages < currentPageIdx); + }, + callback: function() { + if (!isBusy) { + + isBusy = true; + $tfoot.show(); + callLogLoad(true); + } + } + }); + } + } + + if (!isLoggedIn) { + $("#cache_logs_table").find("tfoot").hide(); + } + + if (mapLatLng != null) { + + $("#uxLatLonLink").qtip({ + suppress:false, + content: buildCacheCoordMenu(), + position: { + my: 'left top', + at: 'right top', + adjust: { + x: 10, y: -10 + } + }, + show: { + ready: false, + event: "click", + solo: true + }, hide: { + event: 'unfocus' + }, + style: { + tip: { + corner: false + }, + classes: 'ui-tooltip-widget' + }, + events: { + show: function () { + if ($("#uxLatLon").data("isOverridden")) { + $("a.ccu-restore").show(); + } else { + $("a.ccu-restore").hide(); + } + + if (userDefinedCoords.status != "success") { + $("div.ccu-update").hide(); + } else { + $("div.ccu-update").show(); + } + } + } + }).click(function (e) { + e.preventDefault(); + return false; + }); + + $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({ + overlayShow: false + }); + + setStaticMaps(); + } + }); + + function setStaticMaps() { + + var map = new L.Map('map_preview_canvas', { + center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), + zoom: 10, + doubleClickZoom: false, + dragging: false, + touchZoom: false, + scrollWheelZoom: false, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })); + + var mapLarge = L.map('map_canvas', { + center: [mapLatLng.lat, mapLatLng.lng], + zoom: 14, + doubleClickZoom: true, + dragging: true, + touchZoom: false, + scrollWheelZoom: false, + zoomControl: true, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })) + .addControl(new L.Control.Scale()); + + var tileOptions = { + tileUrl: "https://otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg", + //name: "mpqosm", + //alt: "MapQuest", + subdomains: "1234", + //tileSize: 256, + minZoom: 0, + maxZoom: 18 + }; + + map.addLayer(L.tileLayer(tileOptions.tileUrl, tileOptions)); + + L.tileLayer(tileOptions.tileUrl, tileOptions) + .addTo(mapLarge); + + var pinIcon = L.Icon.extend({ + iconSize: new L.Point(20, 23), + iconAnchor: new L.Point(10,23), + shadowUrl: null + }); + + var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), + { + icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}), + title: mapLatLng.name + }) + .on("click", function () { + document.getElementById("uxlrgMap").scrollIntoView(true); + return false; + }); + + L.marker([mapLatLng.lat, mapLatLng.lng], { + icon: L.icon({iconUrl: '/images/wpttypes/pins/' + mapLatLng.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23]}), + clickable: false, + //zIndexOffset: 99, + title: mapLatLng.name + }).addTo(mapLarge); + + map.addLayer(mkA); + + if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) { + + var llBounds = L.latLngBounds([mapLatLng.lat, mapLatLng.lng], [mapLatLng.lat, mapLatLng.lng]); + + for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) { + + var item = cmapAdditionalWaypoints[x], + ll = [item.lat, item.lng]; + + L.marker(ll, { + icon: L.icon({ iconUrl: '/images/wpttypes/pins/'+ item.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23] }), + title: item.name, + clickable: false + }).addTo(mapLarge); + + llBounds.extend(ll); + } + + window.setTimeout(function () { + mapLarge.fitBounds(llBounds.pad(.5)); + }, 100); + + } + } + + var lnkDH = $('#ctl00_ContentBody_lnkDH'); + function dht() { + try { + $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html())); + var linkText = ((lnkDH.attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt'); + lnkDH + .text(linkText) + .attr('title', linkText); + } catch (e) { + alert(e); + return false; + } + return false; + } + + function buildCacheCoordMenu() { + var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng) + $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" ); + + var $menu = $("<div></div>"); + + $( "#tmpl_CacheCoordinateUpdate" ).tmpl( { + ll: [mapLatLng.lat, mapLatLng.lng], + ll_formatted: mapLatLng.oldLatLngDisplay + } ).appendTo( $menu ); + + $menu.find("button.ccu-button").button(); + + $menu.delegate("button.ccu-parse", "click", function (e) { + e.preventDefault(); + var $this = $(e.target), + $parse =$this.closest('dd').find(".cc-parse-text"), + parseCoords = $.trim($parse.val()); + + if (parseCoords.length == 0) { + alert('Please provide valid coordinates.'); + } else { + $.getJSON("/api/geocode", { parse: parseCoords}, function (response) { + if (response.status == "success") { + var newLatLng = new LatLon(response.data.lat, response.data.lng); + + // update the displayed coords + var dist = curLatLng.rhumbDistanceTo(newLatLng); + var bearingTo = curLatLng.rhumbBearingTo(newLatLng); + var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N"; + + var formats = response.data.formats; + // all these finds, make me feel dirty + $menu + .find("span.ccu-parseverify-coords").text(formats.DM).end() + .find("dl.ccu-parse").hide().end() + .find("dl.ccu-parseverify").show().end() + .find("button.ccu-parseverify-accept") + .data("utm", '') + .data("dm", formats.DM) + .data("lat", response.data.lat) + .data("lng", response.data.lng) + .end(); + } else { + alert("Sorry unable to parse the coordinates you entered."); + } + }); + } + + return false; + }); + + $menu.delegate("button.ccu-parseverify-accept", "click", function (e) { + e.preventDefault(); + var $this = $(this); + // update to webmethod + $.pageMethod("/seek/cache_details.aspx/SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } else { + $("#uxLatLonLink").qtip('hide'); + } + + }); + + return false; + }); + + $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) { + e.preventDefault(); + $menu + .find("input.cc-parse-text").val('').end() + .find("dl.ccu-parse").show().end() + .find("dl.ccu-parseverify").hide().end(); + return false; + }); + + $menu.delegate("a.ccu-restore", "click", function (e) { + e.preventDefault(); + + $.pageMethod("/seek/cache_details.aspx/ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } + }); + + return false; + }); + + return $menu; + } + + GSPK = window.GSPK || {}; + GSPK.Selector = {}; + GSPK.Selector.getSelected = function(){ + var t = null; + if ( window.getSelection ){ + t = window.getSelection(); + }else if(document.getSelection){ + t = document.getSelection(); + }else if(document.selection){ + t = document.selection.createRange().text; + } + return t; + } + //--> + </script> + <script id="loc_favPointsScoreDesc" type="text/html"> + Favorites/Premium Logs + </script> + <script type="text/javascript" language="javascript"> + <!-- + var gotScore = false; + var favDropDown = $('.favorite-dropdown'); + var favContainer = $('.favorite-container'); + + function showFavoriteScore() { + $('#imgFavoriteScore').attr('src', '/images/loading3.gif'); + + $('#uxFavoriteScore').parent().fadeTo(200, .001, function () { + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/score?u=' + userToken, + success: function (scoreResult) { + gotScore = true; + + var score = 0; + + if(scoreResult) { + score = scoreResult; + } + + if(score > 100) { + score = 100; + } + + $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png'); + var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim(); + $('#imgFavoriteScore').attr('alt', pieDesc); + $('#imgFavoriteScore').attr('title', pieDesc); + + $('#uxFavoriteScore').parent().fadeTo(1000, 1); + $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html()); + } + }); + }); + } + var scrollId = false, + logTop = 0; + + if (document.getElementById("cache_logs_container") != null){ + logTop = $("#cache_logs_container").position().top; + } + + + $(window).on("scroll", function() { + if (scrollId != false) { + window.clearTimeout(scrollId); + scrollId = false; + } + + scrollId = window.setTimeout(function() { + if (showScroll){ + if ($(this).scrollTop()< logTop) { + $("#topScroll").fadeOut(); + } else { + $("#topScroll").fadeIn(); + } + }}, 250); + }); + + $(document).bind('mouseup', function (e) { + var $clicked = $(e.target); + if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) { + favDropDown.hide(1, function () { + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + }); + } + }); + + $('#uxFavContainerLink').click(function () { + if ($(favDropDown).is(':visible')) { + favDropDown.hide(1, function(){ + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + }); + } + else { + if (!gotScore) { + showFavoriteScore(); + } + + favContainer.addClass('favorite-container-open'); + favContainer.removeClass('favorite-container'); + favDropDown.show(1); + } + }); + + // End --> + </script> - function callLogLoad(hideFooter) {
- if (screen.width > 1090){
- showScroll = true;
- }
- $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs },
- function (response) {
- if (response.status == "success") {
- appendNewLogs(response);
- if( hideFooter || (totalPages < currentPageIdx) ) {
- $tfoot.hide();
- }
- } else if (response.status == "error" && response.value == "1") {
- // reload the page since the data had expired.
- window.location.reload();
- }
- isBusy = false;
- });
- }
-
- $("#add_to_favorites").click(function () {
-
- if (canUpdateFavoriteStatus) {
- canUpdateFavoriteStatus = false;
-
- var fv = parseInt($(".favorite-value").text());
- fv++;
- $(".favorite-value").text(fv);
-
- var fr = parseInt($(".favorite-rank").text());
- fr--;
- $(".favorite-rank").text(fr);
-
- $("#pnlNonfavoriteCache").fadeOut("fast", function () {
- $("#pnlFavoriteCache").fadeIn("fast");
- });
-
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true',
- success: function () {
- canUpdateFavoriteStatus = true;
- gotScore = false;
- showFavoriteScore();
- }
- });
-
- return false;
- }
- });
-
- $("#remove_from_favorites").click(function () {
- if (canUpdateFavoriteStatus) {
- canUpdateFavoriteStatus = false;
-
- var fv = parseInt($(".favorite-value").text());
- fv--;
- $(".favorite-value").text(fv);
-
- var fr = parseInt($(".favorite-rank").text());
- fr++;
- $(".favorite-rank").text(fr);
-
- $("#pnlFavoriteCache").fadeOut("fast", function () {
- $("#pnlNonfavoriteCache").fadeIn("fast");
- });
-
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false',
- success: function () {
- canUpdateFavoriteStatus = true;
- gotScore = false;
- showFavoriteScore();
- }
- });
-
- return false;
- }
- });
-
- $(function () {
-
- // CSP Section
- if ($("#cspMessage").length) {
-
- var editLink = $('a[href*="report.aspx"]').attr('href');
-
- $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>');
- $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>');
- $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>');
-
- $("#cspGoBack").click(function (e) {
- e.preventDefault();
- window.location = editLink;
- return false;
- });
-
- $("#cspSubmit").click(function (e) {
- e.preventDefault();
- $.pageMethod("/seek/cache_details.aspx/EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.success == true) {
- window.location = '/seek/cache_details.aspx?guid=' + r.guid;
- } else {
- alert("There was an error enabling your cache.");
- }
- });
- return false;
- });
-
- $("#cspConfirm").change(function() {
- if ($("#cspConfirm").is(":checked")) {
- $("#cspSubmit").removeAttr('disabled');
- $("#cspGoBack").attr('disabled', true);
- } else {
- $("#cspSubmit").attr('disabled', true);
- $("#cspGoBack").removeAttr('disabled');
- }
- });
- }
-
-
- //override coords
- if (typeof(userDefinedCoords) != "undefined") {
- if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) {
- mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
- $("#uxLatLon")
- .data("isOverridden", true)
- .addClass("myLatLon");
- } else if (userDefinedCoords.status == "success") {
- mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
- } else {
- $("#uxLatLonLink").contents().unwrap();
- }
- } else {
- $("#uxLatLonLink").contents().unwrap();
- }
-
-
- var cacheNoteText = {
- DefaultText: 'Click to enter a note',
- ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.',
- SavingText: 'Please wait, saving your note...'
- };
-
-
-
- $("time.timeago").timeago();
-
- $(".button").button();
-
- var sn = Cookie.get('sn');
-
- if ($('#trNotPM').length > 0) {
- $('#trNotPM').toggle(!sn);
- }
-
- $("#cache_note").editInPlace({
- callback: function (unused, enteredText) {
- var me = $(this);
-
- var et = $.trim(enteredText);
- if (et.length > 500 ) {
- et = et.substr(0, 500);
- }
- $.pageMethod("/seek/cache_details.aspx/SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) {
- var r = JSON.parse(r.d);
- if (r.success == true) {
- if ($.trim(r.note) == "") {
- $("#cache_note").text(cacheNoteText.DefaultText);
- } else {
- $("#cache_note").text(r.note);
- }
-
- me.effect('highlight', { color: '#ffb84c' }, 'slow');
- } else {
- alert(cacheNoteText.ErrorInSaving);
- $("#cache_note").text(cacheNoteText.DefaultText);
- }
-
- });
-
- return cacheNoteText.SavingText;
- }
- , default_text: cacheNoteText.DefaultText
- , field_type: "textarea"
- , textarea_rows: "7"
- , textarea_cols: "65"
- , show_buttons: true
- , bg_over: "#dad7cb"
- //, callback_skip_dom_reset: true
-
- });
-
- $("#lnk_slippyMap").click(function(e) {
- e.preventDefault();
- loadDynamicMap();
- return false;
- });
-
- $(".inplace_field").live("focus", function () {
- if ($(this).data("created") == null) {
- $(this).data("created", true)
- $(this).countable({
- maxLength: 500
- });
- }
- });
-
- $("#pcn_help").qtip({
- content: 'Enter your own notes here. No other user will be able to access them.',
- position: {
- my: 'top center',
- at: 'bottom center'
- },
- style: {
- classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip'
- },
- });
- $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
-
- if ($("#cache_logs_container").length > 0) {
-
- appendNewLogs(initalLogs);
-
- if (DetectMobileQuick()) {
- $("#pnlButtonLoad")
- .show()
- .find("a.MobileButton")
- .click(function (e) {
- e.preventDefault();
- callLogLoad(false);
- return false;
- })
- .button();
- if(!DetectTierTablet()){
- $("a.MobileButton").addClass("Phone");
- }
- } else {
- $("#pnlLazyLoad").show();
-
- $(window).endlessScroll({
- fireOnce: true,
- fireDelay: 500,
- bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50,
- ceaseFire: function(){
- // stop the scrolling if the last page is reached.
- return (isLoggedIn == false) || (totalPages < currentPageIdx);
- },
- callback: function() {
- if (!isBusy) {
-
- isBusy = true;
- $tfoot.show();
- callLogLoad(true);
- }
- }
- });
- }
- }
-
- if (!isLoggedIn) {
- $("#cache_logs_table").find("tfoot").hide();
- }
-
- if (mapLatLng != null) {
-
- $("#uxLatLonLink").qtip({
- suppress:false,
- content: buildCacheCoordMenu(),
- position: {
- my: 'left top',
- at: 'right top',
- adjust: {
- x: 10, y: -10
- }
- },
- show: {
- ready: false,
- event: "click",
- solo: true
- }, hide: {
- event: 'unfocus'
- },
- style: {
- tip: {
- corner: false
- },
- classes: 'ui-tooltip-widget'
- },
- events: {
- show: function () {
- if ($("#uxLatLon").data("isOverridden")) {
- $("a.ccu-restore").show();
- } else {
- $("a.ccu-restore").hide();
- }
-
- if (userDefinedCoords.status != "success") {
- $("div.ccu-update").hide();
- } else {
- $("div.ccu-update").show();
- }
- }
- }
- }).click(function (e) {
- e.preventDefault();
- return false;
- });
-
- setStaticMaps();
- //$("#staticMap").lazyload();
- }
- });
-
- function setStaticMaps() {
- var llBounds = new L.LatLngBounds();
-
- var map = new L.Map('map_preview_canvas', {
- center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- zoom: 10,
- doubleClickZoom: false,
- dragging: false,
- touchZoom: false,
- scrollWheelZoom: false,
- attributionControl: false
- })
- .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }));
-
- var mapLarge = new L.Map('map_canvas', {
- center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- zoom: 14,
- doubleClickZoom: true,
- dragging: true,
- touchZoom: false,
- scrollWheelZoom: false,
- zoomControl: true,
- attributionControl: false
- })
- .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }))
- .addControl(new L.Control.Scale());
-
- llBounds.extend(new L.LatLng(mapLatLng.lat, mapLatLng.lng));
-
- var tileOptions = {
- tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg",
- name: "mpqosm",
- alt: "MapQuest",
- //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ",
- subdomains: "1234",
- tileSize: 256,
- minZoom: 0,
- maxZoom: 18
- };
-
- map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
- mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
-
- var pinIcon = L.Icon.extend({
- iconSize: new L.Point(20, 23),
- iconAnchor: new L.Point(10,23),
- shadowUrl: null
- });
-
- var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
- title: mapLatLng.name
- })
- .on("click", function () {
- document.getElementById("uxlrgMap").scrollIntoView(true);
- return false;
- });
-
- var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
- clickable: false, zIndexOffset:99, title: mapLatLng.name
- });
-
- map.addLayer(mkA);
- mapLarge.addLayer(mkA2);
-
- $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({
- overlayShow: false
- });
-
- if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) {
-
- for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) {
-
- var item = cmapAdditionalWaypoints[x],
- ll = new L.LatLng(item.lat, item.lng),
- marker = new L.Marker(ll, {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}),
- title: item.name,
- clickable:false
- });
-
- llBounds.extend(ll);
- mapLarge.addLayer(marker);
- }
- var bz = mapLarge.getBoundsZoom(llBounds.pad(1.1));
-
- mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz);
- }
- }
-
- var lnkDH = $('#ctl00_ContentBody_lnkDH');
- function dht() {
- try {
- $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html()));
- var linkText = ((lnkDH.attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt');
- lnkDH
- .text(linkText)
- .attr('title', linkText);
- } catch (e) {
- alert(e);
- return false;
- }
- return false;
- }
-
- function buildCacheCoordMenu() {
- var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng)
- $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" );
-
- var $menu = $("<div></div>");
-
- $( "#tmpl_CacheCoordinateUpdate" ).tmpl( {
- ll: [mapLatLng.lat, mapLatLng.lng],
- ll_formatted: mapLatLng.oldLatLngDisplay
- } ).appendTo( $menu );
-
- $menu.find("button.ccu-button").button();
-
- $menu.delegate("button.ccu-parse", "click", function (e) {
- e.preventDefault();
- var $this = $(e.target),
- $parse =$this.closest('dd').find(".cc-parse-text"),
- parseCoords = $.trim($parse.val());
-
- if (parseCoords.length == 0) {
- alert('Please provide valid coordinates.');
- } else {
- $.getJSON("/api/geocode", { parse: parseCoords}, function (response) {
- if (response.status == "success") {
- var newLatLng = new LatLon(response.data.lat, response.data.lng);
-
- // update the displayed coords
- var dist = curLatLng.rhumbDistanceTo(newLatLng);
- var bearingTo = curLatLng.rhumbBearingTo(newLatLng);
- var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N";
-
- var formats = response.data.formats;
- // all these finds, make me feel dirty
- $menu
- .find("span.ccu-parseverify-coords").text(formats.DM).end()
- .find("dl.ccu-parse").hide().end()
- .find("dl.ccu-parseverify").show().end()
- .find("button.ccu-parseverify-accept")
- .data("utm", '')
- .data("dm", formats.DM)
- .data("lat", response.data.lat)
- .data("lng", response.data.lng)
- .end();
- } else {
- alert("Sorry unable to parse the coordinates you entered.");
- }
- });
- }
-
- return false;
- });
-
- $menu.delegate("button.ccu-parseverify-accept", "click", function (e) {
- e.preventDefault();
- var $this = $(this);
- // update to webmethod
- $.pageMethod("/seek/cache_details.aspx/SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.status == "success") {
- window.location.reload();
- } else {
- $("#uxLatLonLink").qtip('hide');
- }
-
- });
-
- return false;
- });
-
- $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) {
- e.preventDefault();
- $menu
- .find("input.cc-parse-text").val('').end()
- .find("dl.ccu-parse").show().end()
- .find("dl.ccu-parseverify").hide().end();
- return false;
- });
-
- $menu.delegate("a.ccu-restore", "click", function (e) {
- e.preventDefault();
-
- $.pageMethod("/seek/cache_details.aspx/ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.status == "success") {
- window.location.reload();
- }
- });
-
- return false;
- });
-
- return $menu;
- }
-
- GSPK = window.GSPK || {};
- GSPK.Selector = {};
- GSPK.Selector.getSelected = function(){
- var t = null;
- if ( window.getSelection ){
- t = window.getSelection();
- }else if(document.getSelection){
- t = document.getSelection();
- }else if(document.selection){
- t = document.selection.createRange().text;
- }
- return t;
- }
- //-->
- </script>
- <script id="loc_favPointsScoreDesc" type="text/html">
- Favorites/Premium Logs
- </script>
- <script type="text/javascript" language="javascript">
- <!--
- var gotScore = false;
- var favDropDown = $('.favorite-dropdown');
- var favContainer = $('.favorite-container');
-
- function showFavoriteScore() {
- $('#imgFavoriteScore').attr('src', '/images/loading3.gif');
-
- $('#uxFavoriteScore').parent().fadeTo(200, .001, function () {
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/score?u=' + userToken,
- success: function (scoreResult) {
- gotScore = true;
-
- var score = 0;
-
- if(scoreResult)
- score = scoreResult;
-
- if(score > 100)
- score = 100;
-
- $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png');
- var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim();
- $('#imgFavoriteScore').attr('alt', pieDesc);
- $('#imgFavoriteScore').attr('title', pieDesc);
-
- $('#uxFavoriteScore').parent().fadeTo(1000, 1);
- $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html());
- }
- });
- });
- }
- var scrollId = false,
- logTop = $("#cache_logs_container").position().top;
- $(window).on("scroll", function() {
- if (scrollId != false) {
- window.clearTimeout(scrollId);
- scrollId = false;
- }
-
- scrollId = window.setTimeout(function() {
- if (showScroll){
- if ($(this).scrollTop()< logTop) {
- $("#topScroll").fadeOut();
- } else {
- $("#topScroll").fadeIn();
- }
- }}, 250);
- });
-
- $(document).bind('mouseup', function (e) {
- var $clicked = $(e.target);
- if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) {
- favDropDown.hide(1, function () {
- favContainer.addClass('favorite-container');
- favContainer.removeClass('favorite-container-open');
- });
- }
- if ($('#log-dropdown-options').is(':visible') && !$clicked.parents().hasClass('Dropdown')){
- $('#log-dropdown-options').toggleClass('hideMe');
- $('.Dropdown').toggleClass('Active');
- }
- });
-
- $('#uxFavContainerLink').click(function () {
- if ($(favDropDown).is(':visible')) {
- favDropDown.hide(1, function(){
- favContainer.addClass('favorite-container');
- favContainer.removeClass('favorite-container-open');
- });
- }
- else {
- if (!gotScore) {
- showFavoriteScore();
- }
-
- favContainer.addClass('favorite-container-open');
- favContainer.removeClass('favorite-container');
- favDropDown.show(1);
- }
- });
+ <script type="text/javascript">
- $('#dropdown-arrow').on('click', function(e){
- e.preventDefault();
- $('#log-dropdown-options').toggleClass('hideMe');
- $('.Dropdown').toggleClass('Active');
- });
- // End -->
- </script>
- <script type="text/javascript">
$(document).ready(function () {
$('#hlUpgrade').bind('click', function () {
var _this = $(this);
@@ -2331,52 +2214,45 @@ var gaToken = 'UA-2020240-1';//]]> return false;
});
});
- </script>
- <script type="text/javascript">
+
+
+ _gaq.push(['_setCustomVar', 1, 'AccountId', 3409138, 1]);
+
+
_gaq.push(['_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js']);
_gaq.push(['_setAccount', gaToken]);
_gaq.push(['_trackPageview']);
- (function () {
- var ga = document.createElement('script');
- ga.src = ('https:' == document.location.protocol ?
- 'https://ssl' : 'http://www') +
- '.google-analytics.com/ga.js';
- ga.setAttribute('async', 'true');
- document.documentElement.firstChild.appendChild(ga);
- })();
+
$(function () {
$("a.language").click(function (e) {
e.preventDefault();
window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
});
});
- </script>
- <!-- Quantcast Tag -->
- <div id="Quantcast">
- <script type="text/javascript">
- var _qevents = _qevents || [];
- (function () {
- var elem = document.createElement('script');
+ var _qevents = _qevents || [];
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
- elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
- elem.async = true;
- elem.type = "text/javascript";
- var scpt = document.getElementsByTagName('script')[0];
- scpt.parentNode.insertBefore(elem, scpt);
- })();
- </script>
- <script type="text/javascript">
- _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
- </script>
- <noscript>
- <div style="display: none;">
- <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
- alt="Quantcast" />
- </div>
- </noscript>
- </div>
- <!-- End Quantcast tag -->
- <!-- Server: WEB17; Build: Web.HotFix_20130821.1 -->
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+
+
+
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" />
+ </div>
+ </noscript>
+ <!-- Server: WEB07; Build: Tucson.Main.release-20150330.1.Release_270
+ -->
</body>
</html>
diff --git a/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java b/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java index 3fe105d..7404e23 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java +++ b/tests/src/cgeo/geocaching/test/mock/GC2CJPF.java @@ -4,9 +4,11 @@ import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.settings.Settings; +import org.eclipse.jdt.annotation.NonNull; + import java.text.ParseException; import java.util.Date; import java.util.HashMap; @@ -39,11 +41,13 @@ public class GC2CJPF extends MockedCache { return "Tom03"; } + @NonNull @Override public String getOwnerUserId() { return getOwnerDisplayName(); } + @NonNull @Override public CacheSize getSize() { return CacheSize.SMALL; @@ -66,7 +70,7 @@ public class GC2CJPF extends MockedCache { @Override public String getDescription() { - return "<a href=\"http://www.kinderwald.de/\"><b>http://www.kinderwald.de/</b></a><br/><br/>Kleiner Multi über 7 Stationen"; + return "Kleiner Multi über 7 Stationen"; } @Override @@ -121,13 +125,14 @@ public class GC2CJPF extends MockedCache { @Override public Date getHiddenDate() { try { - return GCLogin.parseGcCustomDate("31/07/2010", getDateFormat()); + return GCLogin.parseGcCustomDate("2010-07-31", getDateFormat()); } catch (ParseException e) { // intentionally left blank } return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { diff --git a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.html b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.html index bdc599b..f07ad24 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.html +++ b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.html @@ -4,23 +4,19 @@ <html lang="en" class="no-js">
<head id="ctl00_Head1"><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><title>
GC2JVEH Auf den Spuren des Indianer Jones Teil 1 (Unknown Cache) in Niedersachsen, Germany created by indianerjones, der merlyn,reflektordetektor
-</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" />
- <!--[if lt IE 8]>
- <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" />
- <![endif]-->
- <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" />
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta id="ctl00_ogUrl" property="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC2JVEH&title=auf-den-spuren-des-indianer-jones-teil-1" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="Geocaching: the anytime, anywhere outdoor adventure game." /><meta name="twitter:description" content="There are millions of geocaches worldwide and probably even some near you right now. Visit Geocaching.com to see just how many geocaches are nearby and to get the free Official Geocaching app." /><meta name="twitter:image:src" content="https://www.geocaching.com/play/Content/images/preview-lg.jpg" /><meta name="author" content="Geocaching" /><meta name="DC.creator" content="Geocaching" /><meta name="Copyright" content="Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta name="p:domain_verify" content="107f8f596a30ff1ea307df82db696a5e" /><link href="//fonts.googleapis.com/css?family=Noto+Sans:400,700&subset=latin,latin-ext" rel="stylesheet" type="text/css" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link href="/content/coreCSS?v=LW0HKwsIsnIiQyE_ovDSvnj5M2xR0XjkVV3GaTHUlRI1" rel="stylesheet"/>
+<link href="/css/jqueryui1104/jqUI?v=G2XN-0HsvYJqSZehzmbzhJiIBnEZ9PaVHVjIweqiSx41" rel="stylesheet"/>
+<link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" /><script src="/bundle/modernizer?v=q--nrqGQx_uxNYSvw1AFPQRWLPih7RGk2o0lu9veYaY1"></script>
+<script src="/bundle/coreJS?v=uKjd3XRiFC1C29gkUc0JuDRCF6PuUu7R8PpzGjgXDEc1"></script>
+
+
<script type="text/javascript">
- var _gaq = _gaq || [];
- </script>
- <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script>
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
-
- <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js" type="text/javascript"></script>
- <script type="text/javascript" src="/js/jquery.truncate.min.js"></script>
-
- <script type='text/javascript'>
+
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
+
+ var _gaq = _gaq || [];
+
(function () {
var gads = document.createElement('script');
gads.async = true;
@@ -30,49 +26,67 @@ var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
- </script>
-
-
-
- <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" />
- <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" />
- <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" />
- <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.css" />
- <!--[if IE]>
- <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.ie.css" />
- <![endif]-->
- <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" />
- <script type="text/javascript" src="/js/leaflet/0.5.1/leaflet.js"></script>
- <script type="text/javascript" src="/js/geometa.js"></script>
- <script type="text/javascript">
- var userToken = null,
- urlParams = {},
- mapLatLng = null,
- cmapAdditionalWaypoints = [],
- initalLogs = null, totalLogs = 0, includeAvatars = false;
+ (function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments);
+ }, i[r].l = 1 * new Date();
+ a = s.createElement(o),
+ m = s.getElementsByTagName(o)[0];
+ a.async = 1; a.src = g;
+ m.parentNode.insertBefore(a, m);
+ })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
(function () {
- var e,
- d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); },
- q = window.location.search.substring(1),
- r = /([^&=]+)=?([^&]*)/g;
- while (e = r.exec(q)) {
- urlParams[d(e[1])] = d(e[2]);
- }
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+
})();
+
</script>
-<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC2JVEH&title=auf-den-spuren-des-indianer-jones-teil-1&Submit6=Go" property="og:url" /><meta name="og:description" content="Solve the mystery and then use a smartphone or GPS device to navigate to the solution coordinates. Look for a small hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 3 and difficulty is 5 (out of 5)." property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/8.png" property="og:image" /><meta name="og:title" content="Auf den Spuren des Indianer Jones Teil 1" property="og:title" /><script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="description" content="Auf den Spuren des Indianer Jones Teil 1 (GC2JVEH) was created by indianerjones, der merlyn,reflektordetektor on 11/28/2010. It's a Small size geocache, with difficulty of 5, terrain of 3. It's located in Niedersachsen, Germany.Aufgabe zum Start: Finde die Schattenlinie. !!!Die Skizze mit den Zahlen solltest du mitnehmen!!! Du solltest den cache so beginnen, das du station 2 in der Zeit von mo- fr von 11-19 Uhr und sa von 11-16 Uhr erledigt hast." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
+ + + + <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" /> + <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" /> + <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" /> + <link rel="stylesheet" type="text/css" media="all" href="/static/js/leaflet/0.7.2/leaflet.css" /> + <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" /> + <script type="text/javascript" src="/static/js/leaflet/0.7.2/leaflet.js"></script> + <script type="text/javascript"> + var userToken = null, + urlParams = {}, + mapLatLng = null, + cmapAdditionalWaypoints = [], + initalLogs = null, totalLogs = 0, includeAvatars = false; + + (function () { + var e, + d = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); }, + q = window.location.search.substring(1), + r = /([^&=]+)=?([^&]*)/g; + + while (e = r.exec(q)) { + urlParams[d(e[1])] = d(e[2]); + } + })(); + </script> +<script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:description" content="Solve the mystery and then use a smartphone or GPS device to navigate to the solution coordinates. Look for a small hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 3 and difficulty is 5 (out of 5)." property="og:description" /><meta name="og:title" content="Auf den Spuren des Indianer Jones Teil 1" property="og:title" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/8.png" property="og:image" /><meta name="description" content="Auf den Spuren des Indianer Jones Teil 1 (GC2JVEH) was created by indianerjones, der merlyn,reflektordetektor on 11/28/2010. It's a Small size geocache, with difficulty of 5, terrain of 3. It's located in Niedersachsen, Germany.Aufgabe zum Start: Finde die Schattenlinie. !!!Die Skizze mit den Zahlen solltest du mitnehmen!!! Du solltest den cache so beginnen, das du station 2 in der Zeit von mo- fr von 11-19 Uhr und sa von 11-16 Uhr erledigt hast." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
<body >
- <form name="aspnetForm" method="post" action="/geocache/GC2JVEH_auf-den-spuren-des-indianer-jones-teil-1?Submit6=Go" id="aspnetForm">
+ <form name="aspnetForm" method="post" action="/geocache/GC2JVEH_auf-den-spuren-des-indianer-jones-teil-1" id="aspnetForm">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
-<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="3" />
-<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE1Mzk0NTE5MTEPFgIeBEMuSUQoKVlTeXN0ZW0uSW50NjQsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQcxOTk3NTk3FgJmD2QWBmYPZBYKAgYPFgIeBFRleHQFYjxtZXRhIG5hbWU9IkNvcHlyaWdodCIgY29udGVudD0iQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4iIC8+ZAIHDxYCHwEFRzwhLS0gQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4gLS0+ZAIZDxYCHgRocmVmBR1+L2Nzcy90bG5NYXN0ZXJTY3JlZW4uY3NzP3I9MWQCGg8WAh8CBRV+L2Nzcy90bG5NYWluLmNzcz9yPTFkAh8PFgIeB1Zpc2libGVoZAIBDxYCHgZhY3Rpb24FRS9nZW9jYWNoZS9HQzJKVkVIX2F1Zi1kZW4tc3B1cmVuLWRlcy1pbmRpYW5lci1qb25lcy10ZWlsLTE/U3VibWl0Nj1HbxYWAgsPFgIfAWRkAg0PZBYCAgUPFgIfA2cWCAIBDw8WAh4ISW1hZ2VVcmwFTmh0dHA6Ly9pbWcuZ2VvY2FjaGluZy5jb20vdXNlci9hdmF0YXIvZThhOTdhMDUtYTA1MS00ZGE5LWJjOTMtNmE4MzBiODY2YWZmLmpwZ2RkAgMPFgIfAQVsSGVsbG8sIDxhIGhyZWY9Ii9teS9kZWZhdWx0LmFzcHgiIHRpdGxlPSJWaWV3IFByb2ZpbGUgZm9yIEpvU2FNYUphIiBjbGFzcz0iU2lnbmVkSW5Qcm9maWxlTGluayI+Sm9TYU1hSmE8L2E+ZAIFDw8WAh4LTmF2aWdhdGVVcmwFyAFodHRwczovL3d3dy5nZW9jYWNoaW5nLmNvbS9sb2dpbi9kZWZhdWx0LmFzcHg/UkVTRVQ9WSZyZWRpcj1odHRwJTNhJTJmJTJmd3d3Lmdlb2NhY2hpbmcuY29tJTJmc2VlayUyZmNhY2hlX2RldGFpbHMuYXNweCUzZndwJTNkR0MySlZFSCUyNnRpdGxlJTNkYXVmLWRlbi1zcHVyZW4tZGVzLWluZGlhbmVyLWpvbmVzLXRlaWwtMSUyNlN1Ym1pdDYlM2RHb2RkAgsPFgIfAQUQNDg0IENhY2hlcyBGb3VuZGQCFw8WAh8DZxYCAg0PDxYCHwYFQH4vdHJhY2svc2VhcmNoLmFzcHg/bz0xJnVpZD00ZDQxNjQ2MS1kMWE3LTRjYzUtOGVlNy0zMzZiYjkxMGZlYjhkZAIdDw8WAh8DZ2RkAikPFgIfA2dkAlcPZBYEAgMPFgIfAQUHRW5nbGlzaGQCBQ8WAh4LXyFJdGVtQ291bnQCFBYoZg9kFgICAQ8PFggeD0NvbW1hbmRBcmd1bWVudAUFZW4tVVMeC0NvbW1hbmROYW1lBQ1TZXRUZW1wTG9jYWxlHwEFB0VuZ2xpc2geEENhdXNlc1ZhbGlkYXRpb25oZGQCAQ9kFgICAQ8PFggfCAUFZGUtREUfCQUNU2V0VGVtcExvY2FsZR8BBQdEZXV0c2NoHwpoZGQCAg9kFgICAQ8PFggfCAUFZnItRlIfCQUNU2V0VGVtcExvY2FsZR8BBQlGcmFuw6dhaXMfCmhkZAIDD2QWAgIBDw8WCB8IBQVwdC1QVB8JBQ1TZXRUZW1wTG9jYWxlHwEFClBvcnR1Z3XDqnMfCmhkZAIED2QWAgIBDw8WCB8IBQVjcy1DWh8JBQ1TZXRUZW1wTG9jYWxlHwEFCcSMZcWhdGluYR8KaGRkAgUPZBYCAgEPDxYIHwgFBWRhLURLHwkFDVNldFRlbXBMb2NhbGUfAQUFRGFuc2sfCmhkZAIGD2QWAgIBDw8WCB8IBQVzdi1TRR8JBQ1TZXRUZW1wTG9jYWxlHwEFB1N2ZW5za2EfCmhkZAIHD2QWAgIBDw8WCB8IBQVlcy1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFCEVzcGHDsW9sHwpoZGQCCA9kFgICAQ8PFggfCAUFZXQtRUUfCQUNU2V0VGVtcExvY2FsZR8BBQVFZXN0aR8KaGRkAgkPZBYCAgEPDxYIHwgFBWl0LUlUHwkFDVNldFRlbXBMb2NhbGUfAQUISXRhbGlhbm8fCmhkZAIKD2QWAgIBDw8WCB8IBQVlbC1HUh8JBQ1TZXRUZW1wTG9jYWxlHwEFEM6VzrvOu863zr3Ouc66zqwfCmhkZAILD2QWAgIBDw8WCB8IBQVsdi1MVh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUxhdHZpZcWhdR8KaGRkAgwPZBYCAgEPDxYIHwgFBW5sLU5MHwkFDVNldFRlbXBMb2NhbGUfAQUKTmVkZXJsYW5kcx8KaGRkAg0PZBYCAgEPDxYIHwgFBWNhLUVTHwkFDVNldFRlbXBMb2NhbGUfAQUHQ2F0YWzDoB8KaGRkAg4PZBYCAgEPDxYIHwgFBXBsLVBMHwkFDVNldFRlbXBMb2NhbGUfAQUGUG9sc2tpHwpoZGQCDw9kFgICAQ8PFggfCAUFbmItTk8fCQUNU2V0VGVtcExvY2FsZR8BBQ5Ob3JzaywgQm9rbcOlbB8KaGRkAhAPZBYCAgEPDxYIHwgFBWtvLUtSHwkFDVNldFRlbXBMb2NhbGUfAQUJ7ZWc6rWt7Ja0HwpoZGQCEQ9kFgICAQ8PFggfCAUFaHUtSFUfCQUNU2V0VGVtcExvY2FsZR8BBQZNYWd5YXIfCmhkZAISD2QWAgIBDw8WCB8IBQVyby1STx8JBQ1TZXRUZW1wTG9jYWxlHwEFCFJvbcOibsSDHwpoZGQCEw9kFgICAQ8PFggfCAUFamEtSlAfCQUNU2V0VGVtcExvY2FsZR8BBQnml6XmnKzoqp4fCmhkZAJbD2QWAgIDDxYCHwNoZAJdDxYCHgVjbGFzcwUMc3Bhbi0yNCBsYXN0FgICAQ9kFioCAQ9kFgJmD2QWAgIBDw8WAh8BBQdHQzJKVkVIZGQCAg8WAh8BBZ4BPGEgaHJlZj0iL2Fib3V0L2NhY2hlX3R5cGVzLmFzcHgiIHRhcmdldD0iX2JsYW5rIiB0aXRsZT0iQWJvdXQgQ2FjaGUgVHlwZXMiPjxpbWcgc3JjPSIvaW1hZ2VzL1dwdFR5cGVzLzguZ2lmIiBhbHQ9IlVua25vd24gQ2FjaGUiIHRpdGxlPSJVbmtub3duIENhY2hlIiAvPjwvYT5kAgYPZBYEAgEPFgIfA2dkAgcPFgIfA2hkAgoPZBYGAgEPFgIfAQUCNjlkAgUPZBYCAgEPDxYEHghDc3NDbGFzc2QeBF8hU0ICAmRkAgcPDxYCHwYFRC9zZWVrL2NhY2hlX2Zhdm9yaXRlZC5hc3B4P2d1aWQ9MDcyNzBlOGMtNzJlYy00ODIxLThjYjctYjAxNDgzZjk0Y2I1ZGQCDA8PFgIfA2hkZAINDxYEHwEFSzxwIGNsYXNzPSJXYXJuaW5nIE5vQm90dG9tU3BhY2luZyI+VGhpcyBpcyBhIFByZW1pdW0gTWVtYmVyIE9ubHkgY2FjaGUuPC9wPh8DZ2QCDw8WAh8DaGQCEA8WAh8DaGQCEQ9kFgwCAw9kFgICAQ8WAh8BBRtVVE06IDMyVSBFIDU1MDA2MyBOIDU4MDI2OTZkAg0PDxYCHwYFM2NkcGYuYXNweD9ndWlkPTA3MjcwZThjLTcyZWMtNDgyMS04Y2I3LWIwMTQ4M2Y5NGNiNWRkAg8PDxYCHwYFOGNkcGYuYXNweD9ndWlkPTA3MjcwZThjLTcyZWMtNDgyMS04Y2I3LWIwMTQ4M2Y5NGNiNSZsYz01ZGQCEQ8PFgIfBgU5Y2RwZi5hc3B4P2d1aWQ9MDcyNzBlOGMtNzJlYy00ODIxLThjYjctYjAxNDgzZjk0Y2I1JmxjPTEwZGQCEw8PFgQfBgWPAWh0dHA6Ly9tYXBzLmdvb2dsZS5jb20vbWFwcz9mPWQmaGw9ZW4mc2FkZHI9NTIuMjE2MjUsOS43MTQ0ODMgKEhvbWUgTG9jYXRpb24pJmRhZGRyPTUyLjM3MjI1LDkuNzM1MzY3KEF1ZitkZW4rU3B1cmVuK2RlcytJbmRpYW5lcitKb25lcytUZWlsKzEpHgZUYXJnZXQFBl9ibGFua2RkAhsPZBYIZg8PFgQeCUZvcmVDb2xvcgwfDQIEZGQCAQ8PFgQfDwwfDQIEZGQCAg8PFgIfA2cWAh4Hb25jbGljawU7czJncHMoJzA3MjcwZThjLTcyZWMtNDgyMS04Y2I3LWIwMTQ4M2Y5NGNiNScpO3JldHVybiBmYWxzZTtkAgMPDxYCHwNnFgIfEAUgczJwaG9uZSgnR0MySlZFSCcpO3JldHVybiBmYWxzZTtkAhMPFgIfA2dkAhcPZBYIZg8WAh8DaGQCAQ8PFgIfA2hkZAICDw8WAh8DaGRkAgMPFgIfA2hkAhgPZBYCAgMPDxYCHwEFE05vIGhpbnRzIGF2YWlsYWJsZS4WAh8QBQ1yZXR1cm4gZmFsc2U7ZAIZDxYCHwNoZAIbD2QWBmYPFgIfA2cWBgIBDxYCHgNzcmMFGS9pbWFnZXMvbG9ndHlwZXMvNDgvMi5wbmdkAgMPFgIeCWlubmVyaHRtbAUJRm91bmQgSXQhZAIFDxYCHxIFcjxhIGhyZWY9Ii9zZWVrL2xvZy5hc3B4P0xVSUQ9MDc3NzVjMzUtMDRkMC00YWViLWEzNTYtN2NkOThlYjQ1OGMyIiB0aXRsZT0iVmlldyBZb3VyIExvZyI+TG9nZ2VkIG9uOiAyMDEyLTA2LTI5PC9hPmQCAQ8WBB8SBQ9Mb2cgYSBuZXcgdmlzaXQfAgUfL3NlZWsvbG9nLmFzcHg/SUQ9MTk5NzU5NyZsY249MWQCAg8WAh8DaGQCHA8WAh8DZ2QCHQ8WAh8DaGQCIA9kFgICAw8WAh8SBRNB" />
-<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="ZHZlcnRpc2luZyB3aXRoIFVzZAIkD2QWBgIDDxYCHwcCAhYEAgEPZBYCZg8VA1ZodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL3RyYWNrL2RldGFpbHMuYXNweD9ndWlkPWUzMjkxOWQzLWViOTUtNGQwMy1hNmM0LWQwYWRmZmY5Nzg2NTNodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2ltYWdlcy93cHR0eXBlcy9zbS8yMS5naWYVSWNodGh5b3NhdXJ1cyBIdW1lcnVzZAICD2QWAmYPFQNWaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS90cmFjay9kZXRhaWxzLmFzcHg/Z3VpZD1mMTEyZjY0NS05ZjBkLTRiNmQtODc3NS1jMTg5ODk3ZDk2ZWI1aHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9pbWFnZXMvd3B0dHlwZXMvc20vNjAxNy5naWYRQ2FjaGVyWG1pZWRlIExpc3RkAgcPDxYCHwNnZBYCAgEPDxYEHwEFE1ZpZXcgYWxsIFRyYWNrYWJsZXMfBgVJfi90cmFjay9zZWFyY2guYXNweD93aWQ9MDcyNzBlOGMtNzJlYy00ODIxLThjYjctYjAxNDgzZjk0Y2I1JmNjaWQ9MTk5NzU5N2RkAgkPDxYCHwYFPH4vdHJhY2svc2VhcmNoLmFzcHg/d2lkPTA3MjcwZThjLTcyZWMtNDgyMS04Y2I3LWIwMTQ4M2Y5NGNiNWRkAiUPDxYCHwNnZBYCZg8WAh8HAgMWBgIBD2QWAmYPFQIA3wE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD03NjBlYjMxNC04MzhkLTRhZmMtYWE1Yi00NWIyMjEyZWU0OWMiPlQ1IGFic29sdmllcnQ8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD01YzRiMDkxNS01Y2VjLTRmYTEtOGFmZC00YjNjYTY3ZTAwNGUiPmthaTI3MDc8L2E+ZAICD2QWAmYPFQIOQWx0ZXJuYXRpbmdSb3fVATxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vYm9va21hcmtzL3ZpZXcuYXNweD9ndWlkPTBhMmU0YjMyLTExY2QtNGU0Ni1iNTJiLWFmYTZiZmM4NGRkMiI+VG9EbzwvYT48YnIgLz4gYnkgPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9wcm9maWxlLz9ndWlkPTgyMmMwZmViLTRkZDAtNDMxOC05YmRmLWVhMTk3NjQxOTNhOCI+SC5XYWlpPC9hPmQCAw9kFgJmDxUCAOwBPGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9ib29rbWFya3Mvdmlldy5hc3B4P2d1aWQ9ODMwMTYyYzItNzJkZS00ODc2LWJmMjItMjQ0ZDU5ZjhiYTI3Ij5EaWVzZSBzaW5kIG5vY2ggZiYjMjI4O2xsaWc8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD1mM2I5ZTYwOS02MzNiLTQzYWYtOWUzNC0xZjhmNTRiODZhOWUiPmNlZXdlZTwvYT5kAiYPDxYCHwNnZBYCZg8WAh8HAgEWAgIBD2QWAmYPFQIA3QE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD0xNDU1MTcwOC0wYzNjLTRmOTUtOTM0Mi0xYmIzMTE5ZTZlZmUiPmNnZW8gbW9ja3M8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD00ZDQxNjQ2MS1kMWE3LTRjYzUtOGVlNy0zMzZiYjkxMGZlYjgiPkpvU2FNYUphPC9hPmQCJw9kFhICAQ8PFgIfA2hkZAIDD2QWAgIBDw8WAh8GBUUvaGlkZS93cHRsaXN0LmFzcHg/UmVmV3B0SUQ9MDcyNzBlOGMtNzJlYy00ODIxLThjYjctYjAxNDgzZjk0Y2I1JkRTPTFkZAIHDw8WBh4GUkRTLklECyl2R3JvdW5kc3BlYWsuV2ViLkdQWC5XcHREYXRhU291cmNlcywgVHVjc29uLkNvbW1vbi5MZWdhY3ksIFZlcnNpb249My4wLjQ5ODEuMTMyOTMsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAEeB1JXUFQuSUQoKwQHMTk5NzU5Nx8DaGRkAgkPDxYCHwNnZBYCAgEPDxYEHwYFKy9tYXAvZGVmYXVsdC5hc3B4P2xhdD01Mi4zNzIyNSZsbmc9OS43MzUzNjcfA2dkZAIPDxYCHwEFjwEuLi5vdGhlciBjYWNoZXMgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P3U9aW5kaWFuZXJqb25lcyI+aGlkZGVuPC9hPiBvciA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dWw9aW5kaWFuZXJqb25lcyI+Zm91bmQ8L2E+IGJ5IHRoaXMgdXNlcmQCEQ9kFgYCAQ8WAh8BBf8BLi4ubmVhcmJ5IDxhIGhyZWY9Ii9zZWVrL25lYXJlc3QuYXNweD90eD00MDg2MTgyMS0xODM1LTRlMTEtYjY2Ni04ZDQxMDY0ZDAzZmUmbGF0PTUyLjM3MjI1MCZsbmc9OS43MzUzNjciPmNhY2hlcyBvZiB0aGlzIHR5cGU8L2E+LCA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dHg9NDA4NjE4MjEtMTgzNS00ZTExLWI2NjYtOGQ0MTA2NGQwM2ZlJmxhdD01Mi4zNzIyNTAmbG5nPTkuNzM1MzY3JmY9MSI+dGhhdCBJIGhhdmVuJ3QgZm91bmQ8L2E+ZAIDDxYCHwEFpgEuLi5hbGwgbmVhcmJ5IDxhIGhyZWY9Ii9zZWVrL25lYXJlc3QuYXNweD9sYXQ9NTIuMzcyMjUwJmxuZz05LjczNTM2NyI+Y2FjaGVzPC9hPiwgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P2xhdD01Mi4zNzIyNTAmbG5nPTkuNzM1MzY3JmY9MSI+dGhhdCBJIGhhdmVuJ3QgZm91bmQ8L2E+ZAIFDxYCHwEFfi4uLmFsbCBuZWFyYnkgPGEgaHJlZj0iaHR0cDovL3d3dy53YXltYXJraW5nLmNvbS9kaXJlY3RvcnkuYXNweD9mPTEmbGF0PTUyLjM3MjI1MCZsb249OS43MzUzNjciPndheW1hcmtzIG9uIFdheW1hcmtpbmcuY29tPC9hPmQCEw8WAh8DaGQCFw9kFgICAQ8PFgQfAQW1BzxsaT48YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL21hcC9kZWZhdWx0LmFzcHg/bGF0PTUyLjM3MjI1JmxuZz05LjczNTM3IiB0YXJnZXQ9Il9ibGFuayI+R2VvY2FjaGluZy5jb20gTWFwPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly9tYXBzLmdvb2dsZS5jb20vbWFwcz9xPU4rNTIlYzIlYjArMjIuMzM1K0UrMDA5JWMyJWIwKzQ0LjEyMisoR0MySlZFSCkrIiB0YXJnZXQ9Il9ibGFuayI+R29vZ2xlIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5tYXBxdWVzdC5jb20vbWFwcy9tYXAuYWRwP3NlYXJjaHR5cGU9YWRkcmVzcyZmb3JtdHlwZT1sYXRsb25nJmxhdGxvbmd0eXBlPWRlY2ltYWwmbGF0aXR1ZGU9NTIuMzcyMjUmbG9uZ2l0dWRlPTkuNzM1Mzcmem9vbT0xMCIgdGFyZ2V0PSJfYmxhbmsiPk1hcFF1ZXN0PC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly9tYXBzLnlhaG9vLmNvbS8jbGF0PTUyLjM3MjI1Jmxvbj05LjczNTM3Jnpvb209MTYmcT01Mi4zNzIyNSw5LjczNTM3JmNvbmY9MSZzdGFydD0xJm12dD1tJnRyZj0wIiB0YXJnZXQ9Il9ibGFuayI+WWFob28gTWFwczwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vd3d3LmJpbmcuY29tL21hcHMvZGVmYXVsdC5hc3B4P3Y9MiZsdmw9MTQmc3A9cG9pbnQuNTIuMzcyMjVfOS43MzUzN19HQzJKVkVIIiB0YXJnZXQ9Il9ibGFuayI+QmluZyBNYXBzPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly93d3cub3BlbmN5Y2xlbWFwLm9yZy8/em9vbT0xMiZsYXQ9NTIuMzcyMjUmbG9uPTkuNzM1MzciIHRhcmdldD0iX2JsYW5rIj5PcGVuQ3ljbGVNYXA8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy8/bWxhdD01Mi4zNzIyNSZtbG9uPTkuNzM1Mzcmem9vbT0xMiIgdGFyZ2V0PSJfYmxhbmsiPk9wZW5TdHJlZXRNYXA8L2E+PC9saT4fA2dkZAIbD2QWBgIBDxYCHwEFETE1MCBMb2dnZWQgVmlzaXRzZAIHDw8WAh8GBUN+L3NlZWsvY2FjaGVfbG9nYm9vay5hc3B4P2d1aWQ9MDcyNzBlOGMtNzJlYy00ODIxLThjYjctYjAxNDgzZjk0Y2I1ZGQCCQ8PFgQfBgU9fi9zZWVrL2dhbGxlcnkuYXNweD9ndWlkPTA3MjcwZThjLTcyZWMtNDgyMS04Y2I3LWIwMTQ4M2Y5NGNiNR8BBSJWaWV3IHRoZSBJbWFnZSBHYWxsZXJ5" />
-<input type="hidden" name="__VIEWSTATE2" id="__VIEWSTATE2" value="IG9mIDQgaW1hZ2VzZGQCXw8WAh8DaBYCAgEPD2QWAh4Fc3R5bGUFDHdpZHRoOjEyMHB4O2QCYQ9kFgQCAw8WAh8BBQdFbmdsaXNoZAIFDxYCHwcCFBYoZg9kFgICAQ8PFggfCAUFZW4tVVMfCQUNU2V0VGVtcExvY2FsZR8BBQdFbmdsaXNoHwpoZGQCAQ9kFgICAQ8PFggfCAUFZGUtREUfCQUNU2V0VGVtcExvY2FsZR8BBQdEZXV0c2NoHwpoZGQCAg9kFgICAQ8PFggfCAUFZnItRlIfCQUNU2V0VGVtcExvY2FsZR8BBQlGcmFuw6dhaXMfCmhkZAIDD2QWAgIBDw8WCB8IBQVwdC1QVB8JBQ1TZXRUZW1wTG9jYWxlHwEFClBvcnR1Z3XDqnMfCmhkZAIED2QWAgIBDw8WCB8IBQVjcy1DWh8JBQ1TZXRUZW1wTG9jYWxlHwEFCcSMZcWhdGluYR8KaGRkAgUPZBYCAgEPDxYIHwgFBWRhLURLHwkFDVNldFRlbXBMb2NhbGUfAQUFRGFuc2sfCmhkZAIGD2QWAgIBDw8WCB8IBQVzdi1TRR8JBQ1TZXRUZW1wTG9jYWxlHwEFB1N2ZW5za2EfCmhkZAIHD2QWAgIBDw8WCB8IBQVlcy1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFCEVzcGHDsW9sHwpoZGQCCA9kFgICAQ8PFggfCAUFZXQtRUUfCQUNU2V0VGVtcExvY2FsZR8BBQVFZXN0aR8KaGRkAgkPZBYCAgEPDxYIHwgFBWl0LUlUHwkFDVNldFRlbXBMb2NhbGUfAQUISXRhbGlhbm8fCmhkZAIKD2QWAgIBDw8WCB8IBQVlbC1HUh8JBQ1TZXRUZW1wTG9jYWxlHwEFEM6VzrvOu863zr3Ouc66zqwfCmhkZAILD2QWAgIBDw8WCB8IBQVsdi1MVh8JBQ1TZXRUZW1wTG9jYWxlHwEFCUxhdHZpZcWhdR8KaGRkAgwPZBYCAgEPDxYIHwgFBW5sLU5MHwkFDVNldFRlbXBMb2NhbGUfAQUKTmVkZXJsYW5kcx8KaGRkAg0PZBYCAgEPDxYIHwgFBWNhLUVTHwkFDVNldFRlbXBMb2NhbGUfAQUHQ2F0YWzDoB8KaGRkAg4PZBYCAgEPDxYIHwgFBXBsLVBMHwkFDVNldFRlbXBMb2NhbGUfAQUGUG9sc2tpHwpoZGQCDw9kFgICAQ8PFggfCAUFbmItTk8fCQUNU2V0VGVtcExvY2FsZR8BBQ5Ob3JzaywgQm9rbcOlbB8KaGRkAhAPZBYCAgEPDxYIHwgFBWtvLUtSHwkFDVNldFRlbXBMb2NhbGUfAQUJ7ZWc6rWt7Ja0HwpoZGQCEQ9kFgICAQ8PFggfCAUFaHUtSFUfCQUNU2V0VGVtcExvY2FsZR8BBQZNYWd5YXIfCmhkZAISD2QWAgIBDw8WCB8IBQVyby1STx8JBQ1TZXRUZW1wTG9jYWxlHwEFCFJvbcOibsSDHwpoZGQCEw9kFgICAQ8PFggfCAUFamEtSlAfCQUNU2V0VGVtcExvY2FsZR8BBQnml6XmnKzoqp4fCmhkZAKVAQ8WAh8BBRAmY29weTsgMjAwMC0yMDEzZAIDDxYCHwEFK1NlcnZlcjogV0VCMTc7IEJ1aWxkOiBXZWIuSG90Rml4XzIwMTMwODIxLjFkZA5vRpD1QxLstaWTakNM9Vb2dcT/" />
+<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="ciw8xJq10q5BuddaN5AzWIS9iV2UYaznVFChdeLDQBEYz6upNOzi8cbouu9g78m9mefCv6xtMq3LsiEvRyAA5g0qvFgYdIJeWtnb5K9OeLQ1yiiBYe10u8tac9kNl6/ldYmg5CcNzhFItcWAjy/art71Zh+o2uUGMAdejvrngAJmibos+Vr9Cjajrsn1ZQWaAMK/ZZ8E4onDZscH+fFVzbN60W7Z3tzIT949xbmmXnCuoAFJFRPXtqJfJFSixk7Y6zHVTmoF4IiSjqe6D69m/kumH0D+jy08HDBAcUySjkjnnW7mttgxuvXWnDZNL6eiA333FOOskfPosBOZ5QS7z1jtjpXUJuIZ7l+RGasCXK+rkBoYmWVHetF7w0b8svi1j3Qx0g53DK8YoaWSiPo6gJ9cIC/HmRDLi+CpdCoNMUir1g/1FT0Pd3JEroQ+yD8X1wmtg4qCMy0HqKPaEJdedpMeg6bgL4ewi9c2XSffhr1rl2SH9GiHbucaxQRCCp7YlUWwf1Qs3fRKWe4Hfk+odkayT98E5MC0KWQ9ex+GsPmjGnbb7hfqEQTM10XQUHYk/MNyZ+ULPh5ZQFu2hVdK/fi/MTjwnEVW1U1us8u2f1dbs4RZk8Jy7xm3R3EuxRPX6u9ri+GfYTfy2D4x2L+4ZnT47A57mDrt1r+svMSKeQvHYDR6U1WdZkMmG7UT2pejQ0gBXTbDiC56Pwt/8fOEWnVEobJd5sZNo+Eh/9E6UC7dAjTo/t3XKWWeD56fMZ2cwv9ki3L8b/xt9Z04iuP+NOiW775OrCUVO5vvA/z7HjqFMsAQ2kwJzoR0ohPtTs1tudnfi8mkhPGpcDl7xeZldsXRUIlVK/RvK3wtwp0gi6uQGM1M8szHF8G6To8h489TgcYvNl1OsRVYT8oWv0VJhdVBNP1b1EgEW/5RfqfcVlmGdiqyhc2Lgs+ElbXyF19EQiW8xd41OQjLZYVLfblp3P/orTUaWVq1obflM6XDubEhgn44rNwQ+ikbdy1mhQ3k5YdNFUqNeLENLzxpj4ooqwdZWsErcG7Q2+f0Vc9jDnjmI5mZ8s7H7WVTZUVwpeDoICJr2GbN6rya3g+1ZEk+bxdnF2SBSjxljgUJL0Hcyb13hOqoMIUzOuD3NnkxRqkGeh4QmAX3N/PLIdjUOMPJxKLtgKoidAloEGIUwVxQN7ScrkMoTvljqnj3s85xDvSOW+4kozBugTi406VYOmYmL00IUA66ZetnOqGmut6Adt/5uwYliKuUu+wbOGFU5M7ClwdQ4FsTwoKZsCI0UITngIgpHu7quGSkkI+EBDzE/XHRQKyCJ4OJm8gl6j4bUYl1XndBlduSBdMW1Q8EhO5mKy726gldZIp2DekP+GPgjfrb9KiVqo2+n+660bQ/BTtk3TZm/dPnpW1dGGwS410AHvVnZFpnNP0jp8kVYwkE7ePH7EdapLh4uiQHU3KQ9NWyLMa6TXnh7uBK0rWxevo0zj1/7X7hcam+oYgjeXwGFjd9ivD/qM3fbm5eyi1UUwkNGta2yYSsQFb9MiIGaHVjeYWF26/ukVq106n3pkHRSinzxtm7eyJMBY22UL3bjhluX2pRCCppQyqmJJTqBwK8JBN079+mFBiHvI+4dVVDHX6P3tGNNwJ+BBPXCdEcKmdxxhsE/2qNSvbghC0ju3c8E2A91oNW2qth17vYV50BTxNoi6xL/3N2p5ydgIMqIK7AS0kctMBn5ILo0uO/IGgf2G20USAZ0bfMD7dh1ientRip8V27ODvyP2eMvr1+2TNkFC4EAwpY8GYEd+l+ZikE5HsA9W7C+OKyV1M2t1l2Qu2fqwCzmiaIiDrC4uPrUyjJzxzR9ecHRgYdjfoehXsWTTh8XuYQRtqU6AqVVPJXspdQ+wXmSwuWq0Hk9YnebD9BOungbo/O9WK1Q/Liba47vUytVuPnqDjFAfnsb350uGXcVvypHPUIMHEgeVCcc/PXCMZOw1qKaATv2fOptVPHXnNlW8qScnlJFFA2QdL/RDqAgpgZ8ZsoxTrlzFr0bMiJwejioaDE+QStJ7zEzZKJhp+AqiUIgQG+tgCHNHh1imVympV3rWmK9/u2SEJ0wsEQNEHFl3kttA3JrnSwDPnmnJIzaVQ9kMoXql3tniPriH2/HX7aDmfXORqyoa1jmI/XmwIXc1pS3kKc/b71Ryaq3V8zARdtCJFiwtP9/ns0wrS04KPXFmBAd55VNZeQ1qy/6YBVkmpb608SGAGLt6Xghn++T2y1L07aVZJ9nbjQHO0nRJaEEwmjr4mVf+e7Ks25r98B5ZP5ljH9+n5Qx3Zlh/uhzQRTvZ1NyYBklP5yDhcC1cgnXvSTuBmVAXWlTotb/W3niZhAjpTVRqCRfyvHJIPFvlRH7zyjceT6y53WX/ywUkGyX3M2Z5YNg5Vf1YHJl6DaRrvAAC1ac8gbyHAcHoPf0L1ZrdCCAcNkSsO0hEzP/B3vQ1iVF4ZOmEMpETrfXeGIaNA0uzjtI62omY9++FChUNZM0M9jtdy/htRbNJr1KGEcqtuMe6HLiOy5MAFoem6xPednP7Jeyk0J+lCbiBzZ0GTNMt9Maf6hhGwaHJlAKj0EUv52bSv0PODsE5hQLfVOIQqy/fvV7Zysrg/t2zhN/4RrsPPR5f84lWpc5jLXC8oEs8Fxv4GRnyR092Ar/AVXIMjOACgS6aAhon11lzzy5QAHCdZyYTjG6eP3iQKiYZhxWbvHc1EghIhZb9JjojFeDH6l7EAH1lnpjvoqDqwkdmh+aKqcU4GF9N5p1wsShXTnwwPmyZwHDcxCiqPbR1ZZr12I8L2crCWTBMX46rwdC7RYU+xiVPDD5k4vsFpJiHuu7EMRoGUmBor7HQF5V01to9Ywl6V3nzLKmqF+2dWQESP8Z2XXqHasaybEszQgKKG258dvFWV6phGRUKiFAaJVi0wMUxeTx29xuc2pofuAPZRFcRluLW/1K119tK3SVf29QnF6O+MZDzthlZnlYdKYDYMPq0JspoQ7Aq1c+dw4SomCFEc7QTXKx3WMpZ7B/vx+6b+6Hp19CppXRh6h8JjC0Ze3rAYtz5zql3NwaHK4KrpwauolEFzNgm9mS9TnDS5nkGYJmQIdt+F+yhI6rRBfDQ/60OT/sUMFJxl8noBdbv9n/prSSu8P1CcgvacgEe2NK5qTRuQZnx42xaWw6KF68yM7XgfIXsM6h2eE0QI8t3NVt+j+UNQ6e4r717RFVlT2fMQmouUEEXTaEZAnQinTVngA/6I9LPrSOxkxtPGPfizr7XTsysI3UlCL8NsyTqtTTwr3JatjVtdPhyDq+HQJMMNVkER/NsgVUDlABLe7RuyoyMrzG28QbTeWZwmlY4J2bXHs7vfThAfLEvWTfkWxBQG9k3ukiv34hnMGfHpES6KA7M3J9je0plp93vLre/vxg/u3ep00W+McWYqgVq463A6wpkvTf5fojscXf//GZYAdfv3lfeMTcL+aqcDyGLJY0ivuwdWcE/bAP7dfCwasuSTlXdkn7rMpOmKGluwmghT10Bq2nIhoRjIWjsxMUiCqsV6udcfzxTog70t0QcO15EHEFXhHTITJrGAXYAAieTd6aHZrs/7DBKZ9vuMZ9n9+NGKBw0CAM1EQSFyfWB5GwGjzev8VD6utqJXZJvRs191dFLnBvsss2KVD3XY4klB+6J3Bfd0hUgYazuqIMULfW+/jz3HJO2xxT35umtYAN/4ahfXM3DrB0+texu4O4Eg6Eo3mRu8tcEUuMJyZB9QktyAMuNWbRXgogP+8h7baab/fcY9m3Xw9iYFSFr5ETUVoWydDFJ+M1VjCnPGwncr/RgdUDwP4ID9m7vU3L5EbbDd0unJ+3km4SBf904gsJdPSHIRDhLM0Q9oNqezbotokyYyCEWxuOpJ+NvJmAmzgN7WasCaZbS+uvFTnEmxlcWsP5VuDK6jH045waYOrSkGn8ZOih/QTlpA/8Rl4IPQUcJd3ar/YSpLipS07pg5+8vpcM8dDoUs7P7TVtFt7zo0R4itRH8TDNoXpFVWVPOqjrHHPLXJpz1p+4LNF32n3ohAaoadgc/giYwatu2WF9oaN+KVOxdTksJGi7Quj44QHjNy2wpfw3a5CKA0L3y5EmLWVGo6HH1vreMLHKooPgP+AmZ/Wf7Zm+1MoQ4N4VfMKT1VtbySrzAXFj3xhDMow5bHO6FqP8IZNQ9e693YPlN0oHoeRSOkQkhyET8Q8Ppf7v01HBHynBdkY7hNxBO/1pn5wWM5kxAYLDBRl58qcg+liJJhCi2klcBBRW+/U+7WHCYpFINSO5Dw4QA/nEYpIGsOyjSsekbE42jwFuSYY+ukg8pbLSsWMDXI9NtFnpp5AQa+57auQ9GQVsSCb8TuYbHINBH7vMZz6OwwzOmJMQtDVC5mqkZN0Lx/MOil6iAu02MZQLc69ZnWLklP8ckjvGqHV0h3yhoeD3FI1w1YiqjhUFK0plbExRpCWLGfmZdj39cE60wVBi+rSiU1xIC+O3kRLjZKfM20987EmjB43xywFjUhs+al5kezyr7y5n7BnIE9ftYeEuAIvjF+cOrW8v8/xrsQ3EK2f/Zowd50+T06ahjdtG0R0HWnS7HNAmKsks8TWcCTjwcup3vvURk5VFgMi3Z7BKWApIzpmmihNuqXjn40UsWcHz0kSgL49Lxf/Pmg41gfhK24EGPoA6BVRlgVxr4FIvVBGTidjXpPw/MD5oYi7Sw1n39++im4k2T8U+DiJVBh3yFK6ZCGu+1NpHE8PDq1r4IMh+CdAeYS2hwGRwjNSihghKr5SislRSva+K8oMXoxtiueawvNWnym35YSJ5162UeGUdem7VyMbbEwDT7BQLCHYppgpSRN+N5lkC6Qib1UEGXbuuVnz0iZjl0NaNAHJBZRMXMcn38IEpnGUw9NJjJ0pq9VSv8Fp6c0FlhHtU/CiXd7gGBaNphRqXyQahBNPQAUF03phmbV31zURD14NvWMwzAe+mdxfw+RnHQuTRK910klCSBrMtIKFMl7gJWeBXsxbBVPjMD5MW2XextlzP7Xw3KPAj9M1BH2R1w1e8XOQYUsVLfx2+069LYitjT+ygAjBzXtWyxS8" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="wVwkMMlgqk6U4L/JmqoMR8I2CQj7kg02DAGfNOMzeV0o87nJo+OsyTDeIQLDfLCih0ELxDaPN9B2/1nTyG41riBlfRVY5+WbYzKj5TROzzDFKpC6G4DCUuGedkvoGvoQdUp/F7KwecQG0ecvxsBpcHss4VNS7bQMbzkS40jiei8WcDd81eoBqMw4V6wOr8lKw7FSl56Vww59ENzHuUs5uBWGaNRA6IE4ohfUo3rzlO1CDMCKkCrejL2+HzfpFeiaKOmUEuqr1aF7vRZVhYE50wqTMDFmle4eZkER2SLewTWE70gIn7hQ8KdzIeZyU7bttsP7WZ73thTHPz+b1ONx+KelOqrKydwJlQsA0sP1usemlCzRlKDhTaUymfhG7gYYVFmvzVCTBATTqyqnPRVj/RXvI28AaF2hva9iWfZGtgO8jsvp3/OBrbGUOMyKqKNM3ueCI0irI9+TaCJl1ZlPMXrtAchhyXEGaRK8J3ttrYfs/ZgD28LbKr+vopyOU6NeGJ54kh5ptn6dgvgv4GQcdFsKPiglcF9KbfYsItUHMzqTLjKJcv2S2vDrBbLU62fA0iDdRSTZAzNWzjMijiOR0cNfqPkVS8hWO6ZsbUWb6cxUL9LEuYbNUcTcphkwaSfEk1ZnKJ5qzXiaE8Gju34Az4lSazSToxhGSoctwxjYILIPN0VCO0r2RosBQs9189tPcLY+HfeSPtU35iWo3wftGzo4VWn24wiEeQq1T7gAWY0WFubDz88Y5Yp70C1OYxfhMfy/Bh2jggGZN7iZ3+NwaHbnbAQiWDXXt07sS/8wdoDvjdXAqyratyNK7t1MihGHlrxqT+6DCo8cAzpxBl8Un5fVNdN5O9Ze/vRXOr1p9i6fovryU6sZGbyrb2DfD0/QQ7vRYsd3TQbwDSfzqFEM62nAwnCWlSxRNsaCN+eUrb0LRhllODCYI3iJdkHzyvEEt97QKOKSTzEHpuCRg1CpRwuD42FWYPDSH0nMKavmTPlL23/PuNkGTItgrZBrLYodxUEJ7Tmt9ty5Ouen/XutrXA5Ce70ABNwiYZoQrkbaOAD3YAzNUpB45Dah70W3gXraJShNyBnt/oGFhJzuAUrp5hMLR8HUwZK7XPSqTAZ+CVciBsnWUcruGNaBCi2Tp3QOTTPezAz9AIEPkHo6WJWnwOAzuBDf7o6pdPUgqDqOdkYBMdv/V/cqQYQtKDUUh+ll+q6C96TRs1Zsuw/mTTY+WiX2sSjajLzfe/0RLmVXjlmeTglVN59DS3XirJjN59RicKJa/PK1DxtcMTtgnSpzeDLGYkcsNfoJm7LldDOP9FDHKSLlLxOmrmvbNOsxJgduKiScZsIwtEanpNmEaD3PG+GUJfQMJxv63Jx34iEXy/ANbSOe9QfSC16MbbuqhV1JIV+9svSvenKzmHy1+e0AJO3lWd9iqwz8k/PRWoYj2bFESpvhQI+tn7CYJiwyi2kBZbYNOjei88ZTjTkLCeqKM+F2iNbU5qkCsiY+RT3G1mwmC1AIRs6wtQMJ+56b/5zwQ/0o9qFMDSuDNgBJlTxfg+N0oEPaH2uttZsO+iS4OCf43p0NClkthZI271hwEuRuSn8+w2h3lIf6e4lTDPmp2+G40e4KF8A7xx+o6GjrcTPb6JSvvoVnt2CDHnWsRAZSXbK5fyjj/Qk1as/7dDF8AnBMvEWLNCgQu/1ziSCHcQE4KryMjEBkh41tfjxuwVh7m7jd8IViu+k7+75Sz7I7mwxN6ExAHMX5078cYWqfz/gqmJxF4A9xLELNTlKk9ybx4/kEkZztR+nTlQUt2J+o6bVgUoBhNzVTsTs4slP2yI2uZgT+cqKCX7MUqlxQpIqX+MYTzJR4H4wLEx3Ac2x6t/jh8ntlcNH/iv964TJyzJlIRmVnfmdYIbT9h3OMVNAq8DDzFgHPa9udJosmHlXaqREi77BtJp6NE+EZ2bp4rGYo422wc3QRwolsTJqxcWwTZ2W6X2REPWSooz3Jm/92BV4jnCsak6zZrRVBPSscR+WQdnOtJn6cZlimeQk2dI8ncuZY+5bqXda9cf9SLR5rJhhIYt94UJvc3qegVU4yJjyNGyXr/jjfzQyxKcqb31vvHmTwBW8oP/PbqwykFKHqUZeorY9IL+SR26jtCPw9KcvrS4ZOaufxxV4n5gRWwiuLPRvDX1jMp1t5mTH1FBNX/NPo1clu5SpYv3vjX5UGnBBq6L99AnVj0cjy18HyswaJRt6UK2Ohgw6349/XRqI1kRHCo/TKTufq8xpa3gIvjIdZG5veE3vzyMbM5saEvMPC7hXYTBrNAmhejO4gk/c0RWnV5LB/eoI+tud9WkZaNTclL+Hp/1hFxEpUozdPxL3tY1HG+ekCB1O3KyjE1Xwp0oXN/rve/hr7rttekCW2JzHKLOZWMl7eV7lLyqmrib+9d/96dpxI9hJNpDnX6YPbgeIlC4NHCpOAwAuoFz9n9AglDgZgq5gY2wMbEePZVdXmomquFS55AN4YlOwJ9GUPsxkOdtVWr0CnLnialAK9Cgg/QyAEguWY5rdz9OTmqRoC7L9fOORA9FARkXK+LGOwFHAObDXzD+iVP5ZjU6cvG5py0olHX9S6cVxf4sRldztMbn6mY3pgU2/jWfVontvy2lzrqOq8rV0o95q6H/6l/oYqsSVfgRz3RkDX2kGlbx6q06HoyUJCaEwqIAIPrfjoOAz9jw476w5Lly8xFEdx2taYFDhdT5rR9ZdlPHmI9kxDVXsSsuhkUXj1bq45Fak4PnLu5HbqVN34KmNlA5GUr4pqhRYtJZKt+PAUA0Yk+eInIWac2eDARHzTgCoFnbI2JZXRIUWTuitc2Mt1etOzu4rB6RcQuOBBEXWLQ+xmO4AeEBMNiH0am8uk+N7ndhpnPTo/a/C4DlIAtrMZ+vwDR1xtpCcYOMBI0X3AiVQX6qJcKBTZEmYNcAxM9FgrDXpXRSyehuO6hYgje+SkID4Zuoq0REy8BP1v3UEtguYBQDyaBkWnWAqsgcpDagxeAakrjhWi5mzrmfjmR33R/B0WQWRp/bxPJhVYnE4q0aLnkOjvXcOUJLSx+I7Kvkd/+N+BD70FpSqbUnWrqe8+4vDgbdYYlJ0YV78rV8v3/Jh/MPG3fWlct+CWOHFn5Cn9VZChbClVVrgI4XWgeign5FsUv5zflaWrA6lTx8IDBGaVeUFAMtE0jQBFenH0ll7U2uhrr/MVD9xaYqdGm9GCFFQfApT7oLHBp7KiH8em3D/PfmigV5dUjHmkioi/P0OOCfG61N59D8w4rmLIcDSmBLPoTq/VY7ymq+hYg1No4x2g2sIXShsJBEQZ3NWEiCOdrdjPUPl0gRHaSFkKibLTYDhYCVjRNqZqYkdo4m59YwvW9An0sVk2Dp4j2Pgphv5pS9NHmWSM7PV18LKafqgx3LQ46pm7l6jmOkHlLS4yYyLdpwF4rdlq882CW9m2tVacjccH1xu3SPpnKUl3BGOC/UpoBr8VuRK34c/Jq16F3rxo5StqC4HzuwMp0EbxdpuHGHbXBLGFeaQsFySUtmWtmRhZ4XDLEQUwZGFo2q0oeUQthaNSSLVz0WOauR0H7FO44hHBr544PkoeHrdTlcxbA1k6ZW3GhfjcKaEVVCrIaK7HniWk+bODaV7yO8uziOt47kOvO/R5Do9Hkzk6SfKdZj5lM5jg1goJan+mq6TChw/XSslhgFJN2v3t7rnELEBUc35M8uv9DhktFk1A6r2dzgbIKIw3TYO06b/Bx24m0yCEy3OLTjUXBD87vJAiUgDS5oQDGoGa+Ipm3qu4bt1V9/6Q8XEryWDiVjtslO17244Jk9Fh76LVuqBCrjH0veJfIHK4Mr+Vd6tvH6yeY0GjVXRrdtaXEdNOnY4lRERquJVzm6maNDZWq80uUWjs2GRrCCed4+hi5CREBORvAUeqxvEUvV9EcDwjC2IgiBGgaFPNLvl28j1A9RhSj2zmRbNuRnMEjmIPul0iNFd3DDHz3khdxrWzwMSO5D9QE7FDPmedhvJTXhbfGVeH8AhCKt025JLIEDCgHzWTOVTe8g1et/Zgd2YaGldqvBOBAjwtE0OvBhanevdmTUx2EDGU4xbrgkTKiDBOnbUgYUCF1eCfcyogE3l8imGWbEL8FwuQe3yAP3eGTXC10iul0o5bzTmkJc6S/qvbjfnj7BKpwwN+mWxQysxdDQhiH1rb00B4x7nuimtxZBNhyR9Y9zQ/WMOOFI532R7sQRh7WQKNF1HNuAQtmwTRJvRAL/v1hTpxK8x2vnU/uuI7wPRgPaji6uDc5CpzIRzr7q6cXsc01v58OsQf3uNCGJ50wJKqoT9eLoJrxg9sySh0gi4/SuTK90T9YbEdd8ZnA5EpU90Xki8z7MK3RrAMYKYHC3CgSl5NW5nks0ytqUOTIPcTTBfvY6pYdAX+CJPOGQNKKx7YZ7DH3x7ZSOtqW/esRNQjzhyMYboYd9/E51mTRbre2p1LuzIXXot7Gh4tqf1Mxflc2pS0lavhokyja2EIHnvy5VEr8+czZU9JdqJVzLuwlvdkTXNHNowwxg2Y/MRl3UbVInA57ihdFbCB6M1f0GowhL+z96y8gJIIWKgYx9UI3uauZToCztUDUL5nX/6IgHfkDnWBc/Y6uCp2HslcNSCipLyKoeqgriLtOr1DIol2umx4LL3MxeISfzEmqbJlZoIfFEeGjuRINceAe4vsLdV07HqYZfBbNEbRDxg8rWHL1xAPqZ5c/hAk02kp7g=" />
</div>
<script type="text/javascript">
@@ -92,1124 +106,923 @@ function __doPostBack(eventTarget, eventArgument) { </script>
-<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634981136287450696" type="text/javascript"></script>
+<script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZETFLbdR8wwRMdub1eDU5ILCHE7OhotblLUuaNwx3HQ7rYen0g2&t=635418606520000000" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=ffffffff940d030f" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=ffffffff940d030f" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=VZKNgu1isPaAINPNmSDkniHRmEiR365Y3EPnMj7AXSlsW-OjQIYc7VPoltqjVULZ1g8K9CNDrBJuNvUVOZhFqH3NS7yTvcU3NnCeS_FcC9dLDDQ8Q9UH7PW6s-B2gF04VAooHH3Ji69sDY7LPmffv0PShiGc1206s_RLAIzuI952BGa9reXAmYClCuFJH4FjsvPZoM7oG82eR9HPyOS28x0KmiQ1" type="text/javascript"></script>
-<script src="/ScriptResource.axd?d=H0ET7B4U8EJwmcAbxjSGxSsqhUYAPJWkcrAuejTBaZ7N1SX_jc3D8QuNKUPa0lO4X3QHb4S3pibvaKNYs1ChjXro9ahCfiZGcYIQu6Ypce_q7YOm_PkXbcyD93f6aDlH4D9eFkkuLiE9Ax4WQgrrygMqipqtLqR7mio-gp6w-ttXgLxtrsFRt-pUjltSCvHgWUwBtVr9wTSTuzeTLswFqWhBmRPpN7g52pLMsR4cwsSOiAKUeb6dRJ_DZWWUA7Gz0XyQM93WLdA3NKoaC8qUufQM3ZOa5RAudzueB87VFLfeuhZXxK1-AsHyrJkHMiOGwGZjN55yCPtP1BEwdRcWpCJwU7Y_efv4APmLdYZJuvt4AxhKqZdv9FBT2n8FSDrgUdJXxmOVf_5r2_lt_khWegXBwRoygGjD3nKfQf8Q-zpyIsJZZDzQ8Td_2c9eDB4Zy1LRk5dNsNZy6hAaWo_Uq50DOnrNf0LY0qwB1ZAd9b-kZLlEUQjaCXSSBeCccOLbgDalKaxQ15-fEh-R_Lqgt1720fRQyzlevhgNz5vknnm2hF_vHLKlKAoJWuuSIFEiIgEz-JeplpCgAtzjjo0mJ2Zdl9v_fAQxwE4XgBXmUTaiSmoT6TxPHJPr-3BmMQSZs2qBNbYrFu53gs5JbsKPA0pdzyHLlfP2bYUDBdjB1oCqq5qW0" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=uHIkleVeDJf4xS50Krz-yEJRbXY2x1dOBEdM7W-QkNpgaumdwaefPzMErSeG_W29-lHX6vl5G7uDafHaYWCx8Z9aLlo8tZwVtV42ISp6LhT6LbxuVUWMo5GyApWAyPOqkSkf1vCyntgT-PmPv-C6FWxsbWo1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=Jw6tUGWnA15YEa3ai3FadDbNvwkajNGIHz7aGm4w_MLRMuZ5hwlk3bfOsTs3E4cZZ4ktnTFE_MzciTx4exD15JXabrPKGazf6xj6fW1A8vXJoc3OCqf4cg_BDlVl8fQEsQiziDh4kHnJRWZEQotwuLoezlg1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=LsSN37T_JTo8WmXc7IWe9h7QNKB5hH17UtyHRfQt428U3aulvj53CANg-qZVzIBuh0jojGRwyA5u6DVnEet85JW-JpWduEGLE0VE-2wGHR4yu7MNj7XtsTLWd21Jk8RZENZmygJcHOHGMS1oisYKTWQSIQA1" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=VUtFLQIK94pF36sSxa5M5Q4KyVgkk4aq_Lj3yxNWv9FE_GBcdEQWlyUYzpoPTO27D4G7EbYHTqxoW35XPdin3tebmTxp-wSfJzzK8-nJzs2HapzFx4fuNPR6OjDBQmtyWLMl9s_v9cfV2Mm7C3dG-PYITU2UMwNSjAESeyXFqfw8frZJE2LykLAMOmhcIMdVDEZ3towfhsTqOSZWPCdiMeHylJ16anMqLsL7z0oT5vyUbvIiPYHpYKrAEJIDFxritjPVOv9orjoRf-8NlzG0PwzvCPCUNUOn0q725aaI6lCODxhDBiPw-ciHHQzmbbGdaID-mnjIV9nX6-dgUyOpCAzwZXAoBQPQ6TU3GjtYmetglM7I31meDWRS7sDj-e3m--4pB0SzCNbw9t_ZQ6DjARVQyTvBJksCHM-RcfVHoBtuq9rOTWynsJGmm_Lg2JD7o-KVYJOAuPGcUEcNWxswz-cLWquZQ3_vABHJxAaFz-lnYYwzEyEWn9I2tPIwXjHtZVAB3g0G-dsEEFKNFYXpU1N0r25KNq4NEKXKQg1QI99Bxq6sUV0UkKPNGk0f24VH7_RXyG7L9I3rXDfYaVq1X300crsUh2Cn0-mUkdpiqhtb63KB_jWzXr9HEzeR_socdD-U_PhMKdYigWqerk55eRcMsVPuiRN1yBkFE3GQiZawEqjI0" type="text/javascript"></script>
<script src="../seek/js/cachedetails.js" type="text/javascript"></script>
<script src="../js/latlng.js" type="text/javascript"></script>
- <script type="text/javascript">
+<div>
+
+ <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="C05D5804" />
+</div>
+ <script type="text/javascript">
//<![CDATA[
Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
//]]>
</script>
- <div id="Top" class="SkipLinks">
- <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
- <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
- </div>
- <!--[if lte IE 7]>
- <div class="WarningMessage PhaseOut">
- <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
- </div>
- <![endif]-->
-
-
- <div class="PrintOnly">
- <p>
- <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
- </p>
- <hr />
- </div>
- <header id="ctl00_siteHeader">
- <div class="container">
- <h1 class="Logo span-16">
- <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
- <img src="/images/tlnMasters/geocaching-logo.png" alt="Geocaching" height="43" width="301" />
- </a>
- </h1>
- <div class="ProfileWidget span-8 last">
-
- <div id="ctl00_divSignedIn">
- <p class="Avatar NoBottomSpacing">
- <a id="ctl00_hlHeaderAvatar" accesskey="p" title="Your Profile" href="../my/"><img title="Your Profile" src="http://img.geocaching.com/user/avatar/e8a97a05-a051-4da9-bc93-6a830b866aff.jpg" alt="" style="border-width:0px;" /></a>
- </p>
- <p class="SignedInText">
- <strong>
- Hello, <a href="/my/default.aspx" title="View Profile for JoSaMaJa" class="SignedInProfileLink">JoSaMaJa</a></strong> (<a id="ctl00_hlSignOut" accesskey="s" title="Sign Out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC2JVEH%26title%3dauf-den-spuren-des-indianer-jones-teil-1%26Submit6%3dGo">Sign Out</a>)<br />
- <span id="ctl00_litPMLevel">Premium Member</span>
-
- <strong style="display: block">
- 484 Caches Found</strong>
-
- </p>
- </div>
- </div>
+ <div id="Top" class="SkipLinks">
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
</div>
- </header>
- <nav id="Navigation">
- <div class="container">
- <ul class="Menu">
- <li>
- <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li>
- <li>
- <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Geocaching in 2 Minutes</a></li>
- </ul>
- </li>
-
- <li id="ctl00_liNavProfile">
- <a id="ctl00_hlNavProfile" accesskey="2" title="Your Profile" href="../my/">Your Profile ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavQuickView" accesskey="p" title="Quick View" href="../my/">Quick View</a></li>
- <li>
- <a id="ctl00_hlSubNavLists" accesskey="q" title="Lists" href="../my/lists.aspx">Lists</a></li>
- <li class="ExtraText">
- <a id="ctl00_hlSubNavGeocaches" accesskey="m" title="Geocaches" class="NoRightPadding" href="../my/geocaches.aspx">Geocaches</a>
- (<a id="ctl00_hlSubNavGeocachesYours" accesskey="y" title="Your Geocaches" class="NoSidePadding" href="../my/owned.aspx">Yours</a>)</li>
- <li class="ExtraText">
- <a id="ctl00_hlSubNavProfileTrackables" title="Trackables" class="NoRightPadding" href="../my/travelbugs.aspx">Trackables</a>
- (<a id="ctl00_hlSubNavTrackablesYours" accesskey="8" title="Your Trackables" class="NoSidePadding" href="../track/search.aspx?o=1&uid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">Yours</a>)</li>
- <li>
- <a id="ctl00_hlSubNavPocketQueries" accesskey="9" title="Pocket Queries" href="../pocket/">Pocket Queries</a></li>
- <li>
- <a id="ctl00_hlSubNavFieldNotes" accesskey="0" title="Field Notes" href="../my/fieldnotes.aspx">Field Notes</a></li>
- <li>
- <a id="ctl00_hlSubNavAccount" accesskey="a" title="Account Details" href="../account/">Account Details</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="../seek/">Play ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="../seek/">Hide & Seek a Cache</a></li>
- <li>
- <a id="ctl00_hlSubNavLogCache" title="Log a Cache" href="../my/recentlyviewedcaches.aspx">Log a Cache</a></li>
- <li>
- <a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li>
- <li>
- <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="../track/">Find Trackables</a></li>
- <li>
- <a id="ctl00_hlSubNavGeoTours" title="GeoTours" href="../adventures/geotours">GeoTours</a>
- </li>
- <li>
- <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a>
- <ul class="SubMenu">
-
- <li>
- <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a>
- </li>
-
- <li>
- <a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li>
- <li>
- <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li>
- <li>
- <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
- <li>
- <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
- <li>
- <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop Geocaching</a></li>
- <li>
- <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
- <li>
- <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li>
- <li>
- <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a>
- <ul class="SubMenu">
- <li>
- <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li>
- <li>
- <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li>
- <li>
- <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li>
- <li>
- <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li>
- <li>
- <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li>
- </ul>
- </li>
- <li>
- <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li>
- <li>
- <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/geocaching">Follow Us ▼</a>
- <ul class="SubMenu NavSocialMedia">
- <li>
- <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/geocaching">Facebook</a></li>
- <li>
- <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li>
- <li>
- <a id="ctl00_hlSubNavInstagram" title="Instagram" class="SubNavInstagram" href="http://instagram.com/gogeocaching">Instagram</a></li>
- <li>
- <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li>
- </ul>
- </li>
- </ul>
- <div class="LanguageSelector">
-
-
-<div class="LocaleText">
-
- <strong>Choose Your Language:</strong>
-
-</div>
-<div class="LocaleList">
-
- <div class="selected-language">
-
- <a href="#">English▼</a>
-
- </div>
- <ul class="language-list">
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">Latviešu</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, Bokmål</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li>
-
- <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li>
-
- </ul>
-
-</div>
-<script type="text/javascript">
-
- jQuery(document).ready(function () {
- jQuery(".selected-language a").click(function (e) {
- e.preventDefault();
- var $loc = jQuery(this).parent().next();
- jQuery($loc).show().position({
- of: $loc.parent(),
- my: "left top",
- at: "left bottom",
- offset: "0 0",
- collision: "fit fit"
- });
- jQuery(this).addClass("Expanded");
- jQuery(document).click(function () {
- jQuery(".language-list").fadeOut("fast");
- jQuery(".selected-language a").removeClass("Expanded");
- });
- return false;
- });
- });
-</script>
- </div>
- </div>
- </nav>
- <section id="Content">
+ <!--[if lte IE 8]>
+ <div class="WarningMessage PhaseOut">
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+ </div>
+ <![endif]-->
- <div class="container">
- <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
- <p>
- <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
- </p>
-
- </div>
- <div id="ctl00_divContentMain" class="span-24 last">
-
-
-
- <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
-
- <p>
- <a href="#" class="CoordInfoLink">
- <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC2JVEH</span>
- <span class="arrow">▼</span> </a>
- </p>
-
-</div>
-<div id="dlgClipboard">
- <input type="text" class="TextFormat" />
- <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close">
- x</a>
-</div>
-<script type="text/javascript">
- $("a.CoordInfoLink").click(function (e) {
- e.preventDefault();
-
- $("#dlgClipboard")
- .show()
- .position({
- of: $("a.CoordInfoLink"),
- my: "right top",
- at: "right bottom",
- offset: "0 5"
- })
- .find("input")
- .val('http://coord.info/' + $('.CoordInfoCode').text())
- .focus()
- .select();
-
- $(document).mouseup(function (e) {
- if ($(e.target).parent("div#dlgClipboard").length == 0) {
- $(this).unbind(e);
- $("div#dlgClipboard").hide();
- }
- });
-
- return false;
- });
-
-
-</script>
-
- <div class="span-17">
- <div class="span-17 last BottomSpacing" id="cacheDetails">
- <p class="cacheImage">
- <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/8.gif" alt="Unknown Cache" title="Unknown Cache" /></a>
- </p>
-
- <h2 class="NoBottomSpacing">
- <span id="ctl00_ContentBody_CacheName">Auf den Spuren des Indianer Jones Teil 1</span>
- </h2>
- <div class="minorCacheDetails Clear">
- <div id="ctl00_ContentBody_mcd1">
- A cache by <a href="http://www.geocaching.com/profile/?guid=af08f081-faf4-4992-8268-1e16ab4677a9&wid=07270e8c-72ec-4821-8cb7-b01483f94cb5&ds=2">indianerjones, der merlyn,reflektordetektor</a>
- </div>
- <div id="ctl00_ContentBody_mcd2">
- Hidden
- :
- 2010-11-28
-
- </div>
- <div>
-
- </div>
- </div>
- </div>
- <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-6 BottomSpacing">
-
- <dl>
- <dt>
- Difficulty:</dt>
- <dd>
- <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars5.gif" alt="5 out of 5" /></span>
- </dd>
- </dl>
- <dl>
- <dt>
- Terrain:</dt>
- <dd>
- <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars3.gif" alt="3 out of 5" /></span>
- </dd>
- </dl>
-
- </div>
- <div id="ctl00_ContentBody_size" class="CacheSize span-5">
-
- <p class="AlignCenter">
- Size: <span class="minorCacheDetails"><img src="/images/icons/container/small.gif" alt="Size: small" title="Size: small" /> <small>(small)</small></span>
+ <div class="PrintOnly">
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
</p>
-
+ <hr />
</div>
- <div class="span-6 right last">
-
-
- <div class="favorite right">
- <a id="uxFavContainerLink" href="javascript:void(0);">
- <div class="favorite-container"><!-- TODO! -->
- <span class="favorite-value">
- 69
- </span>
- Favorites
- </div>
+ <header id="ctl00_siteHeader">
+ <div class="container">
+ <h1 class="Logo">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
</a>
- <div class="favorite-dropdown">
- <div id="pnlFavoriteCache" class="hideMe">
-
- <ul class="userFavs">
- <li>
- <a href="javascript:void(0);" id="remove_from_favorites">
- Remove from your Favorites
- </a>
- </li>
- </ul>
-
-</div><div id="pnlNonfavoriteCache">
-
- <ul class="userFavs">
- <li>
- <a href="javascript:void(0);" id="add_to_favorites">
- Add to your Favorites
- </a>
- <a id="ctl00_ContentBody_hlFavoritePointsRemaining" title="[Favorite points remaining]" href="/my/favorites.aspx">Favorite points remaining</a>
+ </h1>
+ <div class="ProfileWidget">
+
+ <div id="ctl00_divSignedIn">
+ <ul class="logged-in-user">
+ <li class="li-user">
+ <a class="SignedInProfileLink" href="/my/default.aspx" title="View Your Profile">
+ <span class="avatar">
+ <img id="ctl00_hlHeaderAvatar" src="https://img.geocaching.com/avatar/642d2771-424e-4ee6-beb6-efecde3406fc.jpg" style="border-width:0px;" />
+ </span>
+ <span class="li-user-info">
+ <span>Bananeweizen</span>
+ <span class="cache-count">743 Finds</span>
+ </span>
+ </a>
+ <button type="button" class="li-user-toggle">
+ <svg width="12px" height="7px" viewBox="0 0 12 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g class="arrow" transform="translate(-1277.000000, -25.000000)" stroke="#FFFFFF" fill="#FFFFFF">
+ <path d="M1280.43401,23.3387013 C1280.20315,23.5702719 1280.20315,23.945803 1280.43401,24.1775793 L1284.82138,28.5825631 L1280.43401,32.9873411 C1280.20315,33.2191175 1280.20315,33.5944429 1280.43401,33.8262192 C1280.54934,33.9420045 1280.70072,34 1280.8519,34 C1281.00307,34 1281.15425,33.9422102 1281.26978,33.8262192 L1286.07462,29.0018993 C1286.30548,28.7701229 1286.30548,28.3947975 1286.07462,28.1630212 L1281.26958,23.3387013 C1281.03872,23.106925 1280.66487,23.106925 1280.43401,23.3387013 Z" id="Dropdown-arrow" sketch:type="MSShapeGroup" transform="translate(1283.254319, 28.582435) scale(1, -1) rotate(-90.000000) translate(-1283.254319, -28.582435) "></path>
+ </g>
+ </g>
+ </svg>
+ </button>
+ <ul>
+ <li class="li-settings">
+ <a title="Edit Account Settings" class="icon-settings" href="/account/settings">Settings</a>
+ </li>
+ <li class="li-signout">
+ <a id="ctl00_hlSignOut" accesskey="s" class="sign-out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC2JVEH%26title%3dauf-den-spuren-des-indianer-jones-teil-1">Sign Out</a>
</li>
</ul>
-
-</div>
- <ul>
- <li>
- <img id="imgFavoriteScore" src="/images/loading3.gif" width="20" height="20" alt="Loading" title="Loading"><span id="uxFavoriteScore"> </span>
+ </li>
+ <li class="li-messagecenterheaderwidget li-messages" id="messagecenterheaderwidget">
+ <a class="message-center-icon" href="/account/messagecenter">
+ <span class="msg-center-link-text">Messages</span>
+ </a>
</li>
- <li>
- <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="/seek/cache_favorited.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View Who Favorited this Cache</a>
- </li>
- <li>
- <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a>
+ <li class="li-upgrade">
+
+
</li>
</ul>
</div>
</div>
-
-
- </div>
-
- <p class="Clear">
-
-
- </p>
- <p class="Warning NoBottomSpacing">This is a Premium Member Only cache.</p>
-
-
- <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable">
- <div class="LocationData FloatContainer">
- <div class="span-9">
- <p class="NoBottomSpacing">
- <a href="#" class="edit-cache-coordinates" id="uxLatLonLink" title="Correct these coordinates">
- <strong>
- <span id="uxLatLon">N 52° 22.335 E 009° 44.122</span></strong>
- </a>
- <br />
- <span id="ctl00_ContentBody_LocationSubPanel">
- UTM: 32U E 550063 N 5802696<br />
- </span>
- <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="/wpt/?lat=52.37225&lon=9.735367&detail=1" target="_blank">Other Conversions</a>
- </p>
- </div>
- <div class="span-7 last AlignRight">
- <span id="ctl00_ContentBody_Location">In Niedersachsen, Germany</span><br />
- <span id="lblDistFromHome"><img src="/images/icons/compass/N.gif" alt="N" style="vertical-align:text-bottom" /> N 17.4 km from your home location</span>
- </div>
- </div>
- <div class="DownloadLinks">
- <dl id="Print">
- <dt class="label">
- <span id="ctl00_ContentBody_uxPrintHeader">Print</span>:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5" target="_blank">No Logs</a>
- <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&lc=5" target="_blank">5 Logs</a>
- <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&lc=10" target="_blank">10 Logs</a>
- <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=52.21625,9.714483 (Home Location)&daddr=52.37225,9.735367(Auf+den+Spuren+des+Indianer+Jones+Teil+1)" target="_blank">Driving Directions</a>
- </dd>
- </dl>
- <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;">
- <dt>
- PDF:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a>
- <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a>
- <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a>
- </dd>
- </dl>
- <dl id="Download">
- <dt class="label">
- <span id="ctl00_ContentBody_uxDownloadLabel">Download</span>:
- </dt>
- <dd>
- <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="/software/default.aspx">Read about waypoint downloads</a>
- </dd>
- <dt></dt>
- <dd>
- <input type="submit" name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" /><input type="submit" name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" /><input type="submit" name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('07270e8c-72ec-4821-8cb7-b01483f94cb5');return false;" id="ctl00_ContentBody_btnSendToGPS" /><input type="submit" name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC2JVEH');return false;" id="ctl00_ContentBody_btnSendToPhone" />
- </dd>
- </dl>
- </div>
- </div>
-
- <div class="Note Disclaimer">
- <strong>
- Please note
- </strong>
- Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>.
</div>
-
-
- <div class="Note PersonalCacheNote">
- <strong>
- Personal Cache Note
- </strong>
- <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" />
- <span id="cache_note">
-
- </span>
+ </header>
+ <nav id="Navigation">
+ <div class="container">
+ <a href="../" id="ctl00_A1" class="Logo" title="Geocaching" accesskey="h">
+ <img src="/images/tlnMasters/logo-geocaching@2x.png" alt="Geocaching" width="195" />
+ </a>
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" class="Dropdown" href="../guide/">Learn</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Videos</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="2" class="Dropdown" href="../play/search/">Play</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavFind" accesskey="d" href="../play/search/">Find a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" href="../play/hide/">Hide a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavMap" accesskey="/" href="../map/">View Geocache Map</a></li>
+ <li id="ctl00_liSubNavLogCache">
+ <a id="ctl00_hlSubNavLogCache" href="../my/recentlyviewedcaches.aspx">Log a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" href="../track/">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeoTours" href="../play/geotours">GeoTours</a>
+ </li>
+ <li id="ctl00_liSubNavPocketQueries">
+ <a id="ctl00_hlSubNavPocketQueries" accesskey="9" href="../pocket/">Pocket Queries</a></li>
+ <li id="ctl00_liSubNavFieldNotes">
+ <a id="ctl00_hlSubNavFieldNotes" accesskey="0" href="../my/fieldnotes.aspx">Field Notes</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="3" class="Dropdown" href="../forums/">Community</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" href="../account/referafriend">Refer a Friend</a>
+ </li>
+
+ <li>
+ <a id="ctl00_hlSubNavVolunteers" accesskey="+" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" class="Dropdown" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">USA Shop</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlBecomePremium" href="https://payments.geocaching.com/?upgrade=true">Become a Premium Member</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
</div>
-
- <h3 class="CacheDescriptionHeader">Geocache Description:</h3>
- <div class="UserSuppliedContent">
+ </nav>
+ <section id="Content">
+ <div class="container">
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+ <!--<p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
+ </p>-->
+
+ </div>
+ <div id="ctl00_divContentMain" class="span-24 last">
+ + + + <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
+ + <p> + <a href="#" class="CoordInfoLink"> + <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC2JVEH</span> + <span class="arrow">▼</span> </a> + </p> +
+</div> +<div id="dlgClipboard"> + <input type="text" class="TextFormat" /> + <a href="#" onclick="$('#dlgClipboard').hide();return false;" title="Close" class="Close"> + x</a> +</div> +<script type="text/javascript"> + $("a.CoordInfoLink").click(function (e) { + e.preventDefault(); + + $("#dlgClipboard") + .show() + .position({ + of: $("a.CoordInfoLink"), + my: "right top", + at: "right bottom", + offset: "0 5" + }) + .find("input") + .val('http://coord.info/' + $('.CoordInfoCode').text()) + .focus() + .select(); + + $(document).mouseup(function (e) { + if ($(e.target).parent("div#dlgClipboard").length == 0) { + $(this).unbind(e); + $("div#dlgClipboard").hide(); + } + }); + + return false; + }); + + +</script> + + + <div class="span-17"> + + <div class="span-17 last BottomSpacing" id="cacheDetails"> + <p class="cacheImage"> + <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/8.gif" alt="Mystery Cache" title="Mystery Cache" /></a> + </p> + + <h2 class="NoBottomSpacing"> + <span id="ctl00_ContentBody_CacheName">Auf den Spuren des Indianer Jones Teil 1</span> + </h2> + <div class="minorCacheDetails Clear"> + <div id="ctl00_ContentBody_mcd1"> + A cache by <a href="http://www.geocaching.com/profile/?guid=af08f081-faf4-4992-8268-1e16ab4677a9&wid=07270e8c-72ec-4821-8cb7-b01483f94cb5&ds=2">indianerjones, der merlyn,reflektordetektor</a> + </div> + <div id="ctl00_ContentBody_mcd2"> + Hidden + : + 2010-11-28 + + </div> + <div> + + </div> + </div> + </div> + <div id="ctl00_ContentBody_diffTerr" class="CacheStarLabels span-6 BottomSpacing"> + + <dl> + <dt> + Difficulty:</dt> + <dd> + <span id="ctl00_ContentBody_uxLegendScale" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars5.gif" alt="5 out of 5" /></span> + </dd> + </dl> + <dl> + <dt> + Terrain:</dt> + <dd> + <span id="ctl00_ContentBody_Localize12" title="(1 is easiest, 5 is hardest)"><img src="http://www.geocaching.com/images/stars/stars3.gif" alt="3 out of 5" /></span> + </dd> + </dl> + + </div> + <div id="ctl00_ContentBody_size" class="CacheSize span-5"> + + <p class="AlignCenter"> + Size: <span class="minorCacheDetails"><img src="/images/icons/container/small.gif" alt="Size: small" title="Size: small" /> <small>(small)</small></span> + </p> + + </div> + <div class="span-6 right last"> + + + <div class="favorite right"> + <a id="uxFavContainerLink" href="javascript:void(0);"> + <div class="favorite-container"><!-- TODO! --> + <span class="favorite-value"> + 97 + </span> + Favorites + </div> + </a> + <div class="favorite-dropdown"> + + <ul> + <li> + <img id="imgFavoriteScore" src="/images/loading3.gif" width="20" height="20" alt="Loading" title="Loading"><span id="uxFavoriteScore"> </span> + </li> + <li> + <a id="hlViewWhoFavorited" title="View Who Favorited this Cache" href="/seek/cache_favorited.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View Who Favorited this Cache</a> + </li> + <li> + <a id="hlAboutFavorites" title="About Favorites" href="http://support.groundspeak.com/index.php?pg=kb.page&id=287" target="_blank">About Favorites</a> + </li> + </ul> + </div> + </div> + + + </div> + + <p class="Clear"> + + + + </p> + <p class="Warning NoBottomSpacing">This is a Premium Member Only cache.</p> + + + <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable"> + <div class="LocationData FloatContainer"> + <div class="span-9"> + <p class="NoBottomSpacing"> + <a href="#" class="edit-cache-coordinates" id="uxLatLonLink" title="Correct these coordinates"> + <strong> + <span id="uxLatLon">N 52° 22.335 E 009° 44.122</span></strong> + </a> + <br /> + <span id="ctl00_ContentBody_LocationSubPanel"> + UTM: 32U E 550063 N 5802696<br /> + </span> + <a id="ctl00_ContentBody_lnkConversions" title="Other Conversions" href="/wpt/?lat=52.37225&lon=9.735367&detail=1" target="_blank">Other Conversions</a> + </p> + </div> + <div class="span-7 last AlignRight"> + <span id="ctl00_ContentBody_Location">In Niedersachsen, Germany</span><br /> + <span id="lblDistFromHome"><img src="/images/icons/compass/N.gif" alt="N" style="vertical-align:text-bottom" /> N 392.3 km from your home location</span> + </div> + </div> + <div class="DownloadLinks"> + <dl id="Print"> + <dt class="label"> + <span id="ctl00_ContentBody_uxPrintHeader">Print</span>: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5" target="_blank">No Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&lc=5" target="_blank">5 Logs</a> + <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&lc=10" target="_blank">10 Logs</a> + <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=48.861002,9.186577 (Home Location)&daddr=52.37225,9.735367(Auf+den+Spuren+des+Indianer+Jones+Teil+1)" target="_blank">Driving Directions</a> + </dd> + </dl> + <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;"> + <dt> + PDF: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkPDFPrintNoLogs" href="javascript:pl(0);">No Logs</a> + <a id="ctl00_ContentBody_lnkPDFPrint5Logs" href="javascript:pl(5);">5 Logs</a> + <a id="ctl00_ContentBody_lnkPDFPrint10Logs" href="javascript:pl(10);">10 Logs</a> + </dd> + </dl> + <dl id="Download"> + <dt class="label"> + <span id="ctl00_ContentBody_uxDownloadLabel">Download</span>: + </dt> + <dd> + <a id="ctl00_ContentBody_lnkDownloads" title="Read about waypoint downloads" href="/software/default.aspx">Read about waypoint downloads</a> + </dd> + <dt></dt> + <dd> + <input type="submit" name="ctl00$ContentBody$btnLocDL" value="LOC waypoint file" id="ctl00_ContentBody_btnLocDL" /><input type="submit" name="ctl00$ContentBody$btnGPXDL" value="GPX file" id="ctl00_ContentBody_btnGPXDL" /><input type="submit" name="ctl00$ContentBody$btnSendToGPS" value="Send to My GPS" onclick="s2gps('07270e8c-72ec-4821-8cb7-b01483f94cb5');return false;" id="ctl00_ContentBody_btnSendToGPS" /><input type="submit" name="ctl00$ContentBody$btnSendToPhone" value="Send to My Phone" onclick="s2phone('GC2JVEH');return false;" id="ctl00_ContentBody_btnSendToPhone" /> + </dd> + </dl> + </div> + </div> + + <div class="Note Disclaimer"> + <strong> + Please note + </strong> + Use of geocaching.com services is subject to the terms and conditions <a href="/about/disclaimer.aspx" title="Read Our Disclaimer">in our disclaimer</a>. + </div> + + + <div class="Note PersonalCacheNote"> + <strong> + Personal Cache Note + </strong> + <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" /> + + <span id="cache_note"></span> + </div> + + <h3 class="CacheDescriptionHeader">Geocache Description:</h3> + <div class="UserSuppliedContent"> + <span id="ctl00_ContentBody_ShortDescription">Aufgabe zum Start: Finde die Schattenlinie. !!!Die Skizze mit den Zahlen solltest du mitnehmen!!! Du solltest den cache so beginnen, das du station 2 in der Zeit von mo- fr von 11-19 Uhr und sa von 11-16 Uhr erledigt hast. Achtung: Damit ihr die Zahlenpause in druckbarer Größe sehen könnt müsst ihr über die Bildergalerie gehen nicht über den unten zu sehenden link.....
-</span>
-
- </div>
-
- <br />
- <div class="UserSuppliedContent">
-
- <span id="ctl00_ContentBody_LongDescription"><img src="http://img.geocaching.com/cache/large/1711f8a1-796a-405b-82ba-8685f2e9f024.jpg" /></span>
-
- </div>
-
- <p>
-
-
- </p>
- <p id="ctl00_ContentBody_hints">
- <strong>
- Additional Hints</strong>
- (<a id="ctl00_ContentBody_lnkDH" title="Decrypt" onclick="return false;" href="../seek/#">No hints available.</a>) </p><div id="div_hint" class="span-8 WrapFix">
- </div><div id='dk' style="display: block;" class="span-9 last">
- <span id="ctl00_ContentBody_EncryptionKey" class="right"></span>
- </div>
- <div class="Clear">
- </div>
-
- </div>
-
-
- <div class="span-6 prepend-1 last">
-
-
-<div class="CacheDetailNavigation NoPrint">
- <div id="ctl00_ContentBody_GeoNav_foundStatus" class="FoundStatus">
- <img src="/images/logtypes/48/2.png" id="ctl00_ContentBody_GeoNav_logTypeImage" />
- <p>
- <strong id="ctl00_ContentBody_GeoNav_logText">Found It!</strong>
- <small id="ctl00_ContentBody_GeoNav_logDate"><a href="/seek/log.aspx?LUID=07775c35-04d0-4aeb-a356-7cd98eb458c2" title="View Your Log">Logged on: 2012-06-29</a></small>
- </p>
- </div>
- <a href="/seek/log.aspx?ID=1997597&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log a new visit</a>
- <ul>
- <li><a href="/seek/gallery.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View Gallery</a> (4)</li>
- <li><a href="/my/watchlist.aspx?w=1997597">Watch</a> (8)</li>
- <li><a href="/bookmarks/mark.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&WptTypeID=8">Bookmark</a></li>
- <li><a href="/bookmarks/ignore.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&WptTypeID=8">Ignore</a></li>
- </ul>
-
-</div>
-
-
-
-
- <div id="map_preview_canvas" class="TopSpacing" style="width: 228px; height: 175px;">
- </div>
-
-
-
- <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing">
-
- <h3 class="WidgetHeader">
- Attributes
- </h3>
- <div class="WidgetBody">
- <img src="/images/attributes/winter-yes.gif" alt="available in winter" title="available in winter" width="30" height="30" /> <img src="/images/attributes/flashlight-yes.gif" alt="flashlight required" title="flashlight required" width="30" height="30" /> <img src="/images/attributes/stealth-yes.gif" alt="stealth required" title="stealth required" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/AbandonedBuilding-yes.gif" alt="in abandoned structure" title="in abandoned structure" width="30" height="30" /> <img src="/images/attributes/hike_med-yes.gif" alt="hike between 1km-10km" title="hike between 1km-10km" width="30" height="30" /> <img src="/images/attributes/rappelling-yes.gif" alt="climbing gear" title="climbing gear" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p>
- </div>
-
- </div>
-
-
+</span> + + </div> + + <br /> + <div class="UserSuppliedContent"> + + <span id="ctl00_ContentBody_LongDescription"><img src="http://img.geocaching.com/cache/large/1711f8a1-796a-405b-82ba-8685f2e9f024.jpg" /></span> + + </div> + + <p> + + + </p> + <p id="ctl00_ContentBody_hints"> + <strong> + Additional Hints</strong> + (<a id="ctl00_ContentBody_lnkDH" title="Decrypt" onclick="return false;" href="../seek/#">No hints available.</a>) </p><div id="div_hint" class="span-8 WrapFix"> + </div><div id='dk' style="display: block;" class="span-9 last"> + <span id="ctl00_ContentBody_EncryptionKey" class="right"></span> + </div> + <div class="Clear"> + </div> + + </div> + + + <div class="span-6 prepend-1 last"> + + +<div class="CacheDetailNavigation NoPrint"> + + <a href="/seek/log.aspx?ID=1997597&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log your visit</a> + <ul> + <li><a href="/seek/gallery.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View Gallery</a> (4)</li> + <li><a href="/my/watchlist.aspx?w=1997597">Watch</a> (12)</li> + <li><a href="/bookmarks/mark.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&WptTypeID=8">Bookmark</a></li> + <li><a href="/bookmarks/ignore.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&WptTypeID=8">Ignore</a></li> + </ul> + + +</div> + + + + + <div id="map_preview_canvas" class="TopSpacing" style="width: 228px; height: 175px;"> + </div> + + + + <div id="ctl00_ContentBody_detailWidget" class="CacheDetailNavigationWidget TopSpacing BottomSpacing"> + + <h3 class="WidgetHeader"> + Attributes + </h3> + <div class="WidgetBody"> + <img src="/images/attributes/winter-yes.gif" alt="available in winter" title="available in winter" width="30" height="30" /> <img src="/images/attributes/flashlight-yes.gif" alt="flashlight required" title="flashlight required" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/stealth-yes.gif" alt="stealth required" title="stealth required" width="30" height="30" /> <img src="/images/attributes/hike_med-yes.gif" alt="hike between 1km-10km" title="hike between 1km-10km" width="30" height="30" /> <img src="/images/attributes/rappelling-yes.gif" alt="climbing gear" title="climbing gear" width="30" height="30" /> <img src="/images/attributes/AbandonedBuilding-yes.gif" alt="in abandoned structure" title="in abandoned structure" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <img src="/images/attributes/attribute-blank.gif" alt="blank" title="blank" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p> + </div> + + </div> + + <div id="ctl00_ContentBody_uxBanManWidget" class="InlinePageAds">
-
-
+ + <script type='text/javascript'>
googletag.cmd.push(function() {{
-googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_2eebdd71-383c-43aa-80d3-bab767439802').addService(googletag.pubads());
+googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_0033fcee-df41-4675-8651-cefe70e47341').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
}});
</script>
-<div id='div_2eebdd71-383c-43aa-80d3-bab767439802'>
+<div id='div_0033fcee-df41-4675-8651-cefe70e47341'>
<script type='text/javascript'>
-googletag.cmd.push(function() { googletag.display('div_2eebdd71-383c-43aa-80d3-bab767439802'); });
+googletag.cmd.push(function() { googletag.display('div_0033fcee-df41-4675-8651-cefe70e47341'); });
</script>
</div>
-
- <p>
+ + <p> <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small> </p>
-</div><div class="GoogleAds AlignCenter BottomSpacing">
-
- </div>
- <div class="clear">
- </div>
-
- <span id="ctl00_ContentBody_lnkTravelBugs"></span>
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">
- <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span>
- </h3>
- <div class="WidgetBody">
-
-
- <ul>
-
- <li>
- <a href="http://www.geocaching.com/track/details.aspx?guid=e32919d3-eb95-4d03-a6c4-d0adfff97865" class="lnk">
- <img src="http://www.geocaching.com/images/wpttypes/sm/21.gif" width="16" /><span>Ichthyosaurus Humerus</span></a>
- </li>
-
- <li>
- <a href="http://www.geocaching.com/track/details.aspx?guid=f112f645-9f0d-4b6d-8775-c189897d96eb" class="lnk">
- <img src="http://www.geocaching.com/images/wpttypes/sm/6017.gif" width="16" /><span>CacherXmiede List</span></a>
- </li>
-
- </ul>
-
-
- <div class="TopSpacing">
+</div><div class="GoogleAds AlignCenter BottomSpacing"> + + </div> + <div class="clear"> + </div> + + <span id="ctl00_ContentBody_lnkTravelBugs"></span> + + +<div class="CacheDetailNavigationWidget"> + + <h3 class="WidgetHeader"> + <span id="ctl00_ContentBody_uxTravelBugList_uxInventoryLabel">Inventory</span> + </h3> + <div class="WidgetBody"> + + + <ul> + + <li> + <a href="http://www.geocaching.com/track/details.aspx?guid=e32919d3-eb95-4d03-a6c4-d0adfff97865" class="lnk"> + <img src="http://www.geocaching.com/images/wpttypes/sm/21.gif" width="16" /><span>Ichthyosaurus Humerus</span></a> + </li> + + </ul> + + + <div class="TopSpacing"> <div id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsLinks">
-
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxViewAllTrackableItems" href="../track/search.aspx?wid=07270e8c-72ec-4821-8cb7-b01483f94cb5&ccid=1997597">View all Trackables</a></p>
+ + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxViewAllTrackableItems" href="../track/search.aspx?wid=07270e8c-72ec-4821-8cb7-b01483f94cb5&ccid=1997597">View all Trackables</a></p> -</div>
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View past Trackables</a></p>
- <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p>
- </div>
-
-
- </div>
-
-
-</div>
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">Bookmark Lists</h3>
- <div class="WidgetBody">
-
-
- <ul class="BookmarkList">
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=760eb314-838d-4afc-aa5b-45b2212ee49c">T5 absolviert</a><br /> by <a href="http://www.geocaching.com/profile/?guid=5c4b0915-5cec-4fa1-8afd-4b3ca67e004e">kai2707</a>
- </li>
-
- <li class='AlternatingRow'>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=0a2e4b32-11cd-4e46-b52b-afa6bfc84dd2">ToDo</a><br /> by <a href="http://www.geocaching.com/profile/?guid=822c0feb-4dd0-4318-9bdf-ea19764193a8">H.Waii</a>
- </li>
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=830162c2-72de-4876-bf22-244d59f8ba27">Diese sind noch fällig</a><br /> by <a href="http://www.geocaching.com/profile/?guid=f3b9e609-633b-43af-9e34-1f8f54b86a9e">ceewee</a>
- </li>
-
- </ul>
-
- <p class="NoBottomSpacing">
- <a href="/bookmarks/default.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&WptTypeID=8" title="View all 9 bookmark lists...">View all 9 bookmark lists...</a>
- </p>
-
- </div>
-
-
-</div>
-
-
-
-
-<div class="CacheDetailNavigationWidget">
-
- <h3 class="WidgetHeader">My Bookmark Lists</h3>
- <div class="WidgetBody">
-
-
- <ul class="BookmarkList">
-
- <li class=''>
- <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=14551708-0c3c-4f95-9342-1bb3119e6efe">cgeo mocks</a><br /> by <a href="http://www.geocaching.com/profile/?guid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">JoSaMaJa</a>
- </li>
-
- </ul>
-
- <p class="NoBottomSpacing">
-
- </p>
-
- </div>
-
-
-</div>
-
-
-
-
- </div>
-
-
- <div id="ctl00_ContentBody_bottomSection" class="span-24 last">
-
- <p>
- <br />
-
-
- <p>
+</div> + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxTrackableItemsHistory" href="../track/search.aspx?wid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View past Trackables</a></p> + <p class="NoBottomSpacing"><a id="ctl00_ContentBody_uxTravelBugList_uxWhatAreTrackables" title="What are Trackable Items?" href="../track/default.aspx">What are Trackable Items?</a></p> + </div> + + + </div> + + +</div> + + +<div class="CacheDetailNavigationWidget"> + <h3 class="WidgetHeader"> + Bookmark Lists + </h3> + <div class="WidgetBody"> + + <ul class="BookmarkList"> + + <li class=''> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=760eb314-838d-4afc-aa5b-45b2212ee49c">T5 absolviert</a><br />by <a href="http://www.geocaching.com/profile/?guid=5c4b0915-5cec-4fa1-8afd-4b3ca67e004e">kai2707</a> + </li> + + <li class='AlternatingRow'> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=0a2e4b32-11cd-4e46-b52b-afa6bfc84dd2">ToDo</a><br />by <a href="http://www.geocaching.com/profile/?guid=822c0feb-4dd0-4318-9bdf-ea19764193a8">H.Waii</a> + </li> + + <li class=''> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=830162c2-72de-4876-bf22-244d59f8ba27">Diese sind noch fällig</a><br />by <a href="http://www.geocaching.com/profile/?guid=f3b9e609-633b-43af-9e34-1f8f54b86a9e">ceewee</a> + </li> + + </ul> + + <p class="NoBottomSpacing"> + <a href="/bookmarks/default.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5&WptTypeID=8" title="View all 9 bookmark lists...">View all 9 bookmark lists...</a> + </p> + </div> +</div> + + + + + </div> + + + <div id="ctl00_ContentBody_bottomSection" class="span-24 last"> + + <p> + <br /> + + + <p> <div id="uxlrgMap" class="FloatRight TopSpacing">
-
- <div class="PageBreakBefore">
-
- </div>
- <div class="CDMapWidget">
- <p class="WidgetHeader NoBottomSpacing">
- <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="/map/default.aspx?lat=52.37225&lng=9.735367" target="_blank">View Larger Map</a>
- </p>
-
- <div id="map_canvas" style="width: 325px; height: 325px;">
- </div>
- <p class="WidgetFooter">
- <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a>
- </p>
- </div>
- <div style="display: none;">
- <div id="mapPrintingNotes">
- To print the map in Firefox and Opera, enable background images in the print dialog.
- <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()">
- Close
- </a>
- </div>
- </div>
-
-</div>
+ + <div class="PageBreakBefore"> + + </div> + <div class="CDMapWidget"> + <p class="WidgetHeader NoBottomSpacing"> + <a id="ctl00_ContentBody_uxViewLargerMap" title="View Larger Map" href="/map/default.aspx?lat=52.37225&lng=9.735367" target="_blank">View Larger Map</a> + </p> + + <div id="map_canvas" style="width: 325px; height: 325px;"> + </div> + <p class="WidgetFooter"> + <a id="ctl00_ContentBody_uxNotesAboutPrinting" href="#mapPrintingNotes" class="NoPrint">Notes about Printing Maps</a> + </p> + </div> + <div style="display: none;"> + <div id="mapPrintingNotes"> + To print the map in Firefox and Opera, enable background images in the print dialog. + <a href="#dlgMapPrintWarning" class="dialog" onclick="$.fancybox.close()"> + Close + </a> + </div> + </div> - <p class="NoPrint">
- <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span>
- <br />
- <span id="ctl00_ContentBody_FindText"></span>
- </p>
- <ul class="NoPrint">
- <li>
- ...other caches <a href="/seek/nearest.aspx?u=indianerjones">hidden</a> or <a href="/seek/nearest.aspx?ul=indianerjones">found</a> by this user
- </li>
-
- <li>
- ...nearby <a href="/seek/nearest.aspx?tx=40861821-1835-4e11-b666-8d41064d03fe&lat=52.372250&lng=9.735367">caches of this type</a>, <a href="/seek/nearest.aspx?tx=40861821-1835-4e11-b666-8d41064d03fe&lat=52.372250&lng=9.735367&f=1">that I haven't found</a>
- </li>
- <li>
- ...all nearby <a href="/seek/nearest.aspx?lat=52.372250&lng=9.735367">caches</a>, <a href="/seek/nearest.aspx?lat=52.372250&lng=9.735367&f=1">that I haven't found</a>
- </li>
- <li>
- ...all nearby <a href="http://www.waymarking.com/directory.aspx?f=1&lat=52.372250&lon=9.735367">waymarks on Waymarking.com</a>
- </li>
-
-
- </ul>
- <p class="NoPrint">
- <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span>
- </p>
- <span class="NoPrint">
-
-<ul>
- <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=52.37225&lng=9.73537" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+52%c2%b0+22.335+E+009%c2%b0+44.122+(GC2JVEH)+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=52.37225&longitude=9.73537&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=52.37225&lon=9.73537&zoom=16&q=52.37225,9.73537&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.52.37225_9.73537_GC2JVEH" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=52.37225&lon=9.73537" target="_blank">OpenCycleMap</a></li><li><a href="http://www.openstreetmap.org/?mlat=52.37225&mlon=9.73537&zoom=12" target="_blank">OpenStreetMap</a></li></span>
-</ul>
+</div> + + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxFindLinksHeader" style="font-weight:bold;">Find...</span> + <br /> + <span id="ctl00_ContentBody_FindText"></span> + </p> + <ul class="NoPrint"> + <li> + ...other caches <a href="/seek/nearest.aspx?u=indianerjones">hidden</a> or <a href="/seek/nearest.aspx?ul=indianerjones">found</a> by this user + </li> + + <li> + ...nearby <a href="/seek/nearest.aspx?tx=40861821-1835-4e11-b666-8d41064d03fe&lat=52.372250&lng=9.735367">caches of this type</a>, <a href="/seek/nearest.aspx?tx=40861821-1835-4e11-b666-8d41064d03fe&lat=52.372250&lng=9.735367&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a href="/seek/nearest.aspx?lat=52.372250&lng=9.735367">caches</a>, <a href="/seek/nearest.aspx?lat=52.372250&lng=9.735367&f=1">that I haven't found</a> + </li> + <li> + ...all nearby <a href="http://www.waymarking.com/directory.aspx?f=1&lat=52.372250&lon=9.735367">waymarks on Waymarking.com</a> + </li> + + + </ul> + <p class="NoPrint"> + <span id="ctl00_ContentBody_uxMapLinkHeader" style="font-weight:bold;">For online maps...</span> + </p> + <span class="NoPrint"> + +<ul> + <span id="ctl00_ContentBody_MapLinks_MapLinks"><li><a href="http://www.geocaching.com/map/default.aspx?lat=52.37225&lng=9.73537" target="_blank">Geocaching.com Map</a></li><li><a href="http://maps.google.com/maps?q=N+52%c2%b0+22.335+E+009%c2%b0+44.122+(GC2JVEH)+" target="_blank">Google Maps</a></li><li><a href="http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=latlong&latlongtype=decimal&latitude=52.37225&longitude=9.73537&zoom=10" target="_blank">MapQuest</a></li><li><a href="http://maps.yahoo.com/#lat=52.37225&lon=9.73537&zoom=16&q=52.37225,9.73537&conf=1&start=1&mvt=m&trf=0" target="_blank">Yahoo Maps</a></li><li><a href="http://www.bing.com/maps/default.aspx?v=2&lvl=14&sp=point.52.37225_9.73537_GC2JVEH" target="_blank">Bing Maps</a></li><li><a href="http://www.opencyclemap.org/?zoom=12&lat=52.37225&lon=9.73537" target="_blank">OpenCycleMap</a></li><li><a href="http://www.openstreetmap.org/?mlat=52.37225&mlon=9.73537&zoom=12" target="_blank">OpenStreetMap</a></li></span> +</ul> + + </span> + <ul class="CachePageImages NoPrint"> + <li><a href="http://img.geocaching.com/cache/large/1711f8a1-796a-405b-82ba-8685f2e9f024.jpg" rel="lightbox">indy mit text netz Kopie</a></li><li><a href="http://img.geocaching.com/cache/large/62f39911-86ab-422c-8322-259d0f118848.jpg" rel="lightbox">Spoiler st.1</a></li><li><a href="http://img.geocaching.com/cache/large/b7c3df61-2403-4ce8-87be-41c54244116f.jpg" rel="lightbox">Zahlenpause</a></li> + </ul> + + <div class="InformationWidget Clear"> + <h3> + 195 Logged Visits + </h3> + <div class="EncryptDecrypt"> + <a href="#" class="decrypt-link"> + Decrypt + </a> + </div> + <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 183 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 1 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 7 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 1 <img src="/images/logtypes/23.png" alt="Enable Listing" title="Enable Listing" /> 1 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 1 </p></span> + <p class="HalfLeft"> + <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View Logbook</a> | <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View the Image Gallery of 4 images</a> + </p> + <p class="NoBottomSpacing AlignRight"> + <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links. + </p> + </div> + + <div id="cache_logs_container"> + <table id="cache_logs_table" class="LogsTable NoBottomSpacing"> + <tbody> + </tbody> + <tfoot> + <tr> + <td class="AlignCenter"> + <div id="pnlLazyLoad" style="display: none;"> + <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" /> + Loading Cache Logs... + </div> + <div id="pnlButtonLoad" style="display: none;"> + <a class="MobileButton"> + Load More Logs...</a> + </div> + </td> + </tr> + </tfoot> + </table> + </div> + <p> + <small> + Current Time: <time datetime="2015-03-31T10:40:47Z">03/31/2015 10:40:47 Pacific Daylight Time (17:40 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2015-03-24T00:02:09Z">2015-03-24T00:02:09Z</time> on 03/23/2015 17:02:09 Pacific Daylight Time (00:02 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum + </small> + </p> + <div id="topScroll" class="TopScroll" style="display: none;"> + <a href="#Top"> </a> </div></div><script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl"> + <tr class="log-row" data-encoded="${IsEncoded}"> + <td> + <div class="FloatLeft LogDisplayLeft"> + <p class="logOwnerProfileName"> + <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong> + </p> + <p class="logOwnerBadge"> + <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle} + </p> + <p class="logOwnerAvatar"> + <a href="/profile/?guid=${AccountGuid}">{{if includeAvatars && AvatarImage}} + <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}"> + {{else includeAvatars }} + <img width="48" height="48" src="/images/default_avatar.jpg"> + {{/if}} + </a> + </p> + <p class="logOwnerStats"> + {{if GeocacheFindCount > 0 }} + <img title="Caches Found" src="/images/icons/16/found.png">${GeocacheFindCount} + {{/if}} + </p> + </div> + <div class="FloatLeft LogDisplayRight"> + <div class="HalfLeft LogType"> + <strong> + <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong> + </div> + <div class="HalfRight AlignRight"> + <span class="minorDetails LogDate">${Visited}</span> + </div> + <div class="Clear LogContent"> + {{if LatLonString.length > 0}} + <strong>${LatLonString}</strong> + {{/if}} + <p class="LogText">{{html LogText}}</p> + {{if Images.length > 0}} + <table cellspacing="0" cellpadding="3" class="LogImagesTable"> + {{tmpl(Images) "tmplCacheLogImages"}} + </table> + {{/if}} + + <div class="AlignRight"> + <small><a title="View Log" href="/seek/log.aspx?LUID=${LogGuid}" target="_blank">{{if (userInfo.ID==AccountID)}} + View / Edit Log / Images + {{else}} + View Log + {{/if}} + </a></small> + {{if (userInfo.ID==AccountID)}} + <small><a title="Upload Image" href="/seek/upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small> + {{/if}} + </div> + </div> + </div> + </td> + </tr> + </script><script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl"> + <tr> + <td> + + <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}"> + <img title="Photo" alt="Photo" src="/images/icons/16/photo.png"> + <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span> + </a> + </td> + </tr> + </script><script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl"> + <span class="LogImgTitle"> ${ $('<div /> + ').text($('<div /> + ').text($('<div /> + ').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink"> + + <a target="_blank" href="/seek/log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a> + + <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span> + + {{if (Descr && Descr.length > 0) }} + <br /><p class="LogImgDescription">${ $('<div /> + ').text($('<div /> + ').text($('<div /> + ').html($item.data.Descr).text()).html()).html() }</p> + {{/if}} + </script><script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl"> + <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}"> + <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4> + <dl> + <dt>Original:</dt> + <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd> + </dl> + <dl class="ccu-parse"> + <dt>Change To:</dt> + <dd> + <input type="text" max="40" size="35" class="cc-parse-text"> + <button class="ccu-button ccu-parse">Submit</button> + </dd> + </dl> + <dl class="ccu-parseverify" style="display: none;"> + <dt>Change To:</dt> + <dd> + <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span> + </dd> + <dt> </dt> + <dd> + <button class="ccu-button ccu-parseverify-accept">Accept</button> + <button class="ccu-button ccu-parseverify-cancel">Cancel</button> + </dd> + </dl> + </div> + </script> - </span>
- <ul class="CachePageImages NoPrint">
- <li><a href="http://imgcdn.geocaching.com/cache/large/1711f8a1-796a-405b-82ba-8685f2e9f024.jpg" rel="lightbox">indy mit text netz Kopie</a></li><li><a href="http://imgcdn.geocaching.com/cache/large/62f39911-86ab-422c-8322-259d0f118848.jpg" rel="lightbox">Spoiler st.1</a></li><li><a href="http://imgcdn.geocaching.com/cache/large/b7c3df61-2403-4ce8-87be-41c54244116f.jpg" rel="lightbox">Zahlenpause</a></li>
- </ul>
-
- <div class="InformationWidget Clear">
- <h3>
- 150 Logged Visits
- </h3>
- <div class="EncryptDecrypt">
- <a href="#" class="decrypt-link">
- Decrypt
- </a>
</div>
- <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 139 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 1 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 7 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 1 <img src="/images/logtypes/23.png" alt="Enable Listing" title="Enable Listing" /> 1 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 1 </p></span>
- <p class="HalfLeft">
- <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View Logbook</a>Â |Â <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=07270e8c-72ec-4821-8cb7-b01483f94cb5">View the Image Gallery of 4 images</a>
- </p>
- <p class="NoBottomSpacing AlignRight">
- <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links.
- </p>
- </div>
-
- <div id="cache_logs_container">
- <table id="cache_logs_table" class="LogsTable NoBottomSpacing">
- <tbody>
- </tbody>
- <tfoot>
- <tr>
- <td class="AlignCenter">
- <div id="pnlLazyLoad" style="display: none;">
- <img src="/images/loading2.gif" class="StatusIcon" alt="Loading" />
- Loading Cache Logs...
- </div>
- <div id="pnlButtonLoad" style="display: none;">
- <a class="MobileButton">
- Load More Logs...</a>
- </div>
- </td>
- </tr>
- </tfoot>
- </table>
- </div>
- <p>
- <small>
- Current Time: <time datetime="2013-08-21T21:11:41Z">08/21/2013 21:11:41 Pacific Daylight Time (04:11 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2013-08-18T07:47:10Z">2013-08-18T07:47:10Z</time> on 08/18/2013 00:47:10 Pacific Daylight Time (07:47 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum
- </small>
- </p>
- <div id="topScroll" class="TopScroll" style="display: none;">
- <a href="#Top"> </a> </div></div><script id="tmpl_CacheLogRow" type="text/x-jquery-tmpl">
- <tr class="log-row" data-encoded="${IsEncoded}">
- <td>
- <div class="FloatLeft LogDisplayLeft">
- <p class="logOwnerProfileName">
- <strong><a id="143568283" href="/profile/?guid=${AccountGuid}">${UserName}</a></strong>
- </p>
- <p class="logOwnerBadge">
- <img title="${creator.GroupTitle}" src="${creator.GroupImageUrl}">${creator.GroupTitle}
- </p>
- <p class="logOwnerAvatar">
- <a href="/profile/?guid=${AccountGuid}">{{if includeAvatars && AvatarImage}}
- <img width="48" height="48" src="http://img.geocaching.com/user/avatar/${AvatarImage}">
- {{else includeAvatars }}
- <img width="48" height="48" src="/images/default_avatar.jpg">
- {{/if}}
- </a>
- </p>
- <p class="logOwnerStats">
- {{if GeocacheFindCount > 0 }}
- <img title="Caches Found" src="/images/icons/16/found.png">${GeocacheFindCount}
- {{/if}}
- </p>
- </div>
- <div class="FloatLeft LogDisplayRight">
- <div class="HalfLeft LogType">
- <strong>
- <img title="${LogType}" alt="${LogType}" src="/images/logtypes/${LogTypeImage}"> ${LogType}</strong>
- </div>
- <div class="HalfRight AlignRight">
- <span class="minorDetails LogDate">${Visited}</span>
- </div>
- <div class="Clear LogContent">
- {{if LatLonString.length > 0}}
- <strong>${LatLonString}</strong>
- {{/if}}
- <p class="LogText">{{html LogText}}</p>
- {{if Images.length > 0}}
- <table cellspacing="0" cellpadding="3" class="LogImagesTable">
- {{tmpl(Images) "tmplCacheLogImages"}}
- </table>
- {{/if}}
-
- <div class="AlignRight">
- <small><a title="View Log" href="/seek/log.aspx?LUID=${LogGuid}" target="_blank">{{if (userInfo.ID==AccountID)}}
- View / Edit Log / Images
- {{else}}
- View Log
- {{/if}}
- </a></small>
- {{if (userInfo.ID==AccountID)}}
- <small><a title="Upload Image" href="/seek/upload.aspx?LID=${LogID}" target="_blank">Upload Image</a></small>
- {{/if}}
- </div>
- </div>
- </div>
- </td>
- </tr>
- </script><script id="tmpl_CacheLogImages" type="text/x-jquery-tmpl">
- <tr>
- <td>
-
- <a class="tb_images lnk" rel="tb_images[grp${LogID}]" href="http://img.geocaching.com/cache/log/large/${FileName}" data-title="{{tmpl "tmplCacheLogImagesTitle"}}">
- <img title="Photo" alt="Photo" src="/images/icons/16/photo.png">
- <span>${ $('<div />').text($('<div />').html($item.data.Name).text()).html() }</span>
- </a>
- </td>
- </tr>
- </script><script id="tmpl_CacheLogImagesTitle" type="text/x-jquery-tmpl">
- <span class="LogImgTitle"> ${ $('<div />
- ').text($('<div />
- ').text($('<div />
- ').html($item.data.Name).text()).html()).html() } </span><span class="LogImgLink">
-
- <a target="_blank" href="/seek/log.aspx?LUID=${$item.parent.parent.data.LogGuid}&IID=${ImageGuid}">View Log</a>
-
- <a href="http://img.geocaching.com/cache/log/large/${FileName}">Print Picture</a></span>
-
- {{if (Descr && Descr.length > 0) }}
- <br /><p class="LogImgDescription">${ $('<div />
- ').text($('<div />
- ').text($('<div />
- ').html($item.data.Descr).text()).html()).html() }</p>
- {{/if}}
- </script><script id="tmpl_CacheCoordinateUpdate" type="text/x-jquery-tmpl">
- <div class="ccu-update" data-lat="${ll[0]}" data-lng="${ll[1]}">
- <h4 class="BottomSpacing">Corrected Coordinates (hidden from others)</h4>
- <dl>
- <dt>Original:</dt>
- <dd>${ll_formatted} <a href="#" class="ccu-restore">Restore</a></dd>
- </dl>
- <dl class="ccu-parse">
- <dt>Change To:</dt>
- <dd>
- <input type="text" max="40" size="35" class="cc-parse-text">
- <button class="ccu-button ccu-parse">Submit</button>
- </dd>
- </dl>
- <dl class="ccu-parseverify" style="display: none;">
- <dt>Change To:</dt>
- <dd>
- <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span>
- </dd>
- <dt> </dt>
- <dd>
- <button class="ccu-button ccu-parseverify-accept">Accept</button>
- <button class="ccu-button ccu-parseverify-cancel">Cancel</button>
- </dd>
- </dl>
- </div>
- </script>
-
- </div>
-
- </div>
- </section>
- <footer>
- <div class="container">
- <div class="span-24 last FooterTop">
+ </div>
+ </section>
+ <footer>
+
+ <section class="links wrap">
+ <dl>
+ <dt>Partner With Us</dt>
+ <dd><a id="ctl00_hlFooterJobs" href="http://www.groundspeak.com/jobs.aspx">Jobs</a></dd>
+ <dd><a id="ctl00_lnkTravelAndGeotourism" href="/travel/">GeoTours & Travel</a></dd>
+ <dd><a id="ctl00_lnkBrandedPromotions" href="/brandedpromotions/">Branded Promotions</a></dd>
+ </dl>
-<div class="LocaleText">
-
- <strong>Choose Your Language:</strong>
-
-</div>
-<div class="LocaleList">
-
- <div class="selected-language">
-
- <a href="#">English▼</a>
-
- </div>
- <ul class="language-list">
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Čeština</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">Latviešu</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, Bokmål</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li>
-
- <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li>
-
- </ul>
-
-</div>
-<script type="text/javascript">
+ <dl>
+ <dt>Legal</dt>
+ <dd><a id="ctl00_hlFooterLogo" accesskey="l" href="../about/logousage.aspx">Logo Usage Guidelines</a></dd>
+ <dd><a id="ctl00_hlFooterParksPoliceLink" href="../parksandpolice/">Parks & Police</a></dd>
+ </dl>
- jQuery(document).ready(function () {
- jQuery(".selected-language a").click(function (e) {
- e.preventDefault();
- var $loc = jQuery(this).parent().next();
- jQuery($loc).show().position({
- of: $loc.parent(),
- my: "left top",
- at: "left bottom",
- offset: "0 0",
- collision: "fit fit"
- });
- jQuery(this).addClass("Expanded");
- jQuery(document).click(function () {
- jQuery(".language-list").fadeOut("fast");
- jQuery(".selected-language a").removeClass("Expanded");
- });
- return false;
- });
- });
+ <dl>
+ <dt>Shop Geocaching</dt>
+ <dd><a id="ctl00_lnkUSAShop" href="http://shop.geocaching.com/">USA Shop</a></dd>
+ <dd><a id="ctl00_lnkInternationalShop" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></dd>
+ </dl>
+ <dl>
+ <dt>Contact Us</dt>
+ <dd><a id="ctl00_lnkHelpCenterLink" rel="external" href="http://support.groundspeak.com/index.php?pg=request">Help Center</a></dd>
+ <dd><a id="ctl00_lnkMedia" rel="document" href="../press/faq.aspx">Media Inquiries</a></dd>
+ </dl>
+ + +<div class="language-dropdown"> + <div class="LocaleText"> + Choose Language + </div> + <div class="LocaleList"> + + <div class="selected-language"> + + <a href="#">English</a> + + </div> + <ul class="language-list"> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" class="selected" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Català </a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">ÄŒeÅ¡tina</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Dansk</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Deutsch</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Ελληνικά</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Eesti</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Français</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">日本語</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">í•œêµì–´</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">LatvieÅ¡u</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Magyar</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Nederlands</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, BokmÃ¥l</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">Polski</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Português</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">РуÑÑкий</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl20_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl20$uxLocaleItem','')">Suomi</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl21_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl21$uxLocaleItem','')">Svenska</a></li> + + </ul> + + </div> +</div> +<script type="text/javascript"> + + jQuery(document).ready(function () { + jQuery(".selected-language a").click(function (e) { + e.preventDefault(); + var $loc = jQuery(this).parent().next(); + jQuery($loc).show().position({ + of: $loc.parent(), + my: "left bottom", + at: "left top-10", + collision: "fit fit" + }); + jQuery(this).addClass("Expanded"); + jQuery(document).click(function () { + jQuery(".language-list").fadeOut("fast"); + jQuery(".selected-language a").removeClass("Expanded"); + }); + return false; + }); + }); </script>
- </div>
- </div>
- <div class="container column-container">
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- About</strong>
+ </section>
+
+ <section class="copyright">
+ <div class="container">
+ <p>
+ © 2000-2015
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" href="../about/privacypolicy.aspx">Privacy Policy</a>
</p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li>
- <li>
- <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li>
- <li>
- <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li>
- <li>
- <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Press</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li>
- <li>
- <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li>
- <li>
- <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li>
- <li>
- <a id="ctl00_hlFooterLogo" accesskey="l" title="Logo Usage Guidelines" href="../about/logousage.aspx">Logo Usage Guidelines</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Questions & Suggestions</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li>
- <li>
- <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li>
- <li>
- <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li>
- <li>
- <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Resources</strong>
- </p>
- <ul class="FooterLinks">
- <li>
- <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li>
- <li>
- <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li>
- <li>
- <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li>
- </ul>
- </div>
- <div class="column">
- <p class="FooterLinksHeader">
- <strong>
- Follow Us</strong>
- </p>
- <ul class="FooterLinks FollowUsLinks">
- <li>
- <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a></li>
- <li>
- <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a></li>
- <li>
- <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/gogeocaching/"></a></li>
- <li>
- <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a></li>
- </ul>
- </div>
- </div>
- <div class="FooterBottom">
- <div class="container">
- <p>
- Copyright
- © 2000-2013
- <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
- All Rights Reserved.
- <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
- |
- <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a>
- </p>
- </div>
+ <ul class="links-social">
+ <li>
+ <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/geocaching/"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a>
+ </li>
+ </ul>
+ </div>
+ </section>
+ </footer>
+ <div class="SkipLinks">
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
</div>
- </footer>
- <div class="SkipLinks">
- <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
- </div>
<script type="text/javascript">
@@ -1218,15 +1031,20 @@ $(function() { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', var userDefinedCoords = {"status":"success","data":{"isUserDefined":false,"oldLatLngDisplay":"N 52° 22.335' E 009° 44.122'"}};
mapLatLng = {"lat":52.37225,"lng":9.73537,"type":8,"name":"Auf den Spuren des Indianer Jones Teil 1"};
var ccConversions = [{"t":"Decimal","k":"DD","d":"WGS84","v":"52.372250, 009.735367"},{"t":"DDD MM SS.SSS","k":"DMS","d":"WGS84","v":"N 52° 22' 20.100\" E 009° 44' 07.321\""},{"t":"UTM","k":"UTM","d":"WGS84","v":"32U E 550063 N 5802696"}];
-var dh=true;userInfo = {ID: 4793174};
-userToken = '4OB3GFHLRR3CGMZFUAPD6CWPE24ZHP6Q7KCBEDNYY5CUNWNQIA32GZPVPFMH6IGAEYKVNNSFLMQ7BBGFDKQBT3BZGZBYKVQ4H5BWKD6MVBKYBTM627XPOUSUP6U4JF7NKKEOYJ4A6LEG2T5B6MG5AMMFOS27KNE4U2BAU4KGHNNCGHRXDAQ7IGVLP2WYPUSOZZMJF23ZKPTFBDSI6SX3L46257PU4EWNOF34N6M4P4XNG3BXC7IQ';
-includeAvatars = true;
+var dh=true;userInfo = {ID: 3409138};
+userToken = 'ID5R2NBJDBPQYVKRP2QCKFMGOD72N345U34TRF3HIUOES7I3DEYZLGMWQENANSEL75TH743VWQXA4PRVBZVB2UFIVLT5HYFG73BJY737PC6AVOROLQCJBHWZ5WOPA4ZCUMZSO7RLBORYFW5XH4FZERAO4GV6P6EU7MMIJWQFCMKSWDLYPOETOG7C45IQCAL3KQH2HBW2ZEKNQEUZGEYPWMRCNR5G5ZK3DVSHQO3IXXDQGJ2DC6PA';
+includeAvatars = false;
var lat=52.37225, lng=9.735367, guid='07270e8c-72ec-4821-8cb7-b01483f94cb5';
-initalLogs = {"status":"success", "data": [{"LogID":341065611,"CacheID":1997597,"LogGuid":"44bac55c-ddc2-46d6-92b1-8f0fec5888ce","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Ein absolutes Highlight mit tollen locations! ich bin jetzt schon total gespannt auf den Bonus!<br />DfdC!","Created":"2013-08-18","Visited":"2013-08-16","UserName":"stevielie","MembershipLevel":3,"AccountID":4273519,"AccountGuid":"b1c98d59-3caa-4f8a-9395-782f5488c196","Email":"","AvatarImage":"ee3a63b4-339a-4272-94dc-ce49042fa62e.jpg","GeocacheFindCount":2146,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":340681128,"CacheID":1997597,"LogGuid":"497bab09-2744-4bfd-a115-26de91242e62","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Geniales Teil und der Bonus kommt auch noch dran. Da freue ich mich schon wieder drauf. Irgendwie kommt man sich hier am Final vor wie in einer Szene aus Indiana Jones :-). Danke für dieses Hammerteil!<br />TB's:waren keine mehr im Final!","Created":"2013-08-17","Visited":"2013-08-16","UserName":"tyrion84","MembershipLevel":3,"AccountID":4586198,"AccountGuid":"02ffc7f5-7210-4440-9662-e6feb38dbd30","Email":"","AvatarImage":"f9aed8b6-98d8-462b-8ba6-85e30818f079.jpg","GeocacheFindCount":1429,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":340546349,"CacheID":1997597,"LogGuid":"2b886278-9b75-4840-aa09-08d41cdb2bba","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute haben wir uns mal auf die Spuren von Indi begeben. Ich muss schon sagen ein sehr cooler Cache und schöner Final Location! Ich fand den Cache sehr stimmig und ich freue mich schon auf den Bonus.<br /><br />THX4$ & Grüße aus Kassel<br />Deadman<br /><br /><br />#3881","Created":"2013-08-16","Visited":"2013-08-16","UserName":"x Deadman x","MembershipLevel":3,"AccountID":837113,"AccountGuid":"a0b2cd6f-bb90-4593-8510-c29e24f66c55","Email":"","AvatarImage":"429117dd-d776-4d71-923f-e9783a46bfb5.jpg","GeocacheFindCount":3899,"GeocacheHideCount":17,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":337102227,"CacheID":1997597,"LogGuid":"118a9859-3a2d-4438-b821-1bc196b8b667","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hier ist schon so viel geschrieben worden, mir selbst fehlen dafür die Worte, das Gesamtpaket ist irgendwie \"anders\" und deshalb wohl so stimmig. Bin auf den Bonus gespannt.<br /><br />Danke dafür, viele Grüße und DFDC!","Created":"2013-08-07","Visited":"2013-08-04","UserName":"Legobob","MembershipLevel":3,"AccountID":2222979,"AccountGuid":"7975f326-c25d-42ce-bf3d-7b3c50c22485","Email":"","AvatarImage":"","GeocacheFindCount":2556,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":332880491,"CacheID":1997597,"LogGuid":"b0f3443a-a6dc-429c-a655-fb0b2641a18b","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Über kurz und lang konnten wir einige Rätsel knacken, sodass Team Lollipopformel, turisas und ich heute die Outdoorteile erledigten. Im Teamwork konnte jeder seine Stärken ausleben, so hatten wir viel Spaß und Erfolg. TFTC","Created":"2013-07-25","Visited":"2013-07-24","UserName":"N52E10","MembershipLevel":3,"AccountID":3019401,"AccountGuid":"b1928314-527b-4259-b5a7-d952cb5f8bf6","Email":"","AvatarImage":"c075d4d2-086b-4ee7-82fe-ae0cddc39356.jpg","GeocacheFindCount":4258,"GeocacheHideCount":36,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":332852128,"CacheID":1997597,"LogGuid":"15896db4-100a-482a-9a00-141d80d6a758","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Nachdem bereits Gestern eine Cacherunde zusammen mit N52E10 in und um Hannover sehr erfolgreich gewesen ist, verabredeten wir uns für heute wieder!<br /><br />Die Caches waren größtenteils schon im Vorfeld gelöst, beim ein oder anderen musste auch noch vor Ort ein wenig nachgearbeitet werden.<br /><br />Die meisten Rätsel hatten es wirklich in sich, so dass die Vorarbeiten umfangreicher waren als das eigentliche Suchen vor Ort.<br /><br />Danke an alle Owner, die für diesen Rätselspaß verantwortlich waren und auch Danke an das heutige Team, hat jede menge Spass gemacht, soviel, dass man sich ja schon Morgen wieder sieht!!!!<br /><br />TFTC<br /><br />Turisas","Created":"2013-07-25","Visited":"2013-07-24","UserName":"turisas","MembershipLevel":3,"AccountID":1818511,"AccountGuid":"211db984-da49-4ad9-a363-916f6add5749","Email":"","AvatarImage":"ae219979-f647-463a-b1f6-faf177095bdd.jpg","GeocacheFindCount":3534,"GeocacheHideCount":7,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":335382811,"CacheID":1997597,"LogGuid":"9e326d73-016e-4ed4-b57e-0d48d4b63490","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf Heutiger Freitagsrunde mit Captain Sam, Lollipopformel1 und Thomstone diesen Cache erfolgreich gefunden.<br /><br />der Final hat mir sehr gut gefallen, für einen moment kam ich mir selber vor wie Indiana Jones.<img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /><br /><br />TFTC MFG Bikerboy-GF","Created":"2013-08-02","Visited":"2013-07-12","UserName":"Bikerboy-GF","MembershipLevel":3,"AccountID":3427910,"AccountGuid":"8ac7af26-85bc-49e1-870c-c6a3da343f5b","Email":"","AvatarImage":"d782bf50-4c14-491c-bcf8-f2c8cfd2628b.jpg","GeocacheFindCount":2446,"GeocacheHideCount":5,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":334055186,"CacheID":1997597,"LogGuid":"d47c8a55-1a57-46f1-8cea-815a3a90a500","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute hatte ich das Glück einfach im richtigen Team unterwegs zu sein um den letzten Part dieses Mysterys zu besuchen. Das Team Lollipopformel1 hatte die Vorarbeit geleistet und ich hatte lediglich beim Outdoorpart zielsicher die richtige Nase. Die location ist schon krass.<br /><br />Dank an den Owner für diesen Cache <img src=\"/images/icons/icon_smile_cool.gif\" border=\"0\" align=\"middle\" /><br />Gruß <font color=\"green\"> Captain Sam </font>","Created":"2013-07-29","Visited":"2013-07-12","UserName":"Captain Sam","MembershipLevel":3,"AccountID":1276722,"AccountGuid":"9dfc3233-2016-4eaf-a661-00fb586d2337","Email":"","AvatarImage":"87a8d758-cb5c-4e80-a7e0-b08cc302ac65.jpg","GeocacheFindCount":4465,"GeocacheHideCount":68,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":330918315,"CacheID":1997597,"LogGuid":"779c810d-d8f2-43f9-a680-ef6af522a36e","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hatta auch gefunden!<br /><br />Dieser wurde in mehreren Abschnitten absolviert.<br />Vor längerer Zeit angefangen und immer wieder abgebrochen, mal aus Zeitmangel mal wegen Betriebsbindheit.<br />Aber heute im größeren Team konnte dieser Cache endlich zum Abschluss gebracht werden.<br />Coole Lokation, aber was hier noch Spät am Abend los ist.............unglaublich.<br />Wir wurden sogar als Dealer abgestempelt, aber auch das konnte uns nicht aufhalten.<br />Im Team konnte der besorgte Anwohner aus der Umgebung überzeugt werden das wir voll harmlos sind.<br />War wohl auch nicht Seine die Erste Begegnung mit \"Komischen Leuten\".<br />Nachdem wir dann wieder ungestört waren konnte alles wieder verstaut werden und es ging weiter.<br /><br />Danke für diesen Cache<br />Gruss Team Lollipopformel1","Created":"2013-07-18","Visited":"2013-07-12","UserName":"Team Lollipopformel1","MembershipLevel":3,"AccountID":501013,"AccountGuid":"0821d4e4-6f60-4eac-a305-28ccd0d7fbbf","Email":"","AvatarImage":"3d89c256-7203-4037-98f4-530a5cd9e162.jpg","GeocacheFindCount":12577,"GeocacheHideCount":51,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":325094291,"CacheID":1997597,"LogGuid":"9b370af6-55ee-4aef-a212-29f612ea78c7","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Diesen Cache haben wir lange vor uns her geschoben. Warum eigentlich? Wo es los geht, war uns schon immer klar. Vor Ort wurde dann bald klar, was zu tun ist. Station 1 war schnell gefunden und es war auch klar, wo wir nun hin mussten, aber es blieben nur noch 15 Minuten bis zum Ende des Zeitfensters. Aber geschafft! Uff! Der Rest war auch richtig klasse! Das Final mussten wir ein bisschen suchen, aber wir schafften es noch im Hellen! Toller Ort.","Created":"2013-06-26","Visited":"2013-06-26","UserName":"Katringo","MembershipLevel":3,"AccountID":4077756,"AccountGuid":"e1510042-182e-402e-a7a1-fa6521d99cf2","Email":"","AvatarImage":"4d0e8420-4325-455a-be4d-07e9aea37675.jpg","GeocacheFindCount":2783,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":324464909,"CacheID":1997597,"LogGuid":"7590ad07-05d7-4e01-b978-a1233b303668","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Jippieh, ein erfolgreicher Sonntag :D<br />Nach der Arbeit erst ein Zufallscachefund auf der Hunderunde, aber eigentlich war geplant hier und heute endlich das Final zu finden. Die Dose konnte nach kurzer Suche gefunden werden und nun freue ich mich schon auf den Bonus ;)<br />Danke für den Cache!","Created":"2013-06-23","Visited":"2013-06-23","UserName":"BretonePaul","MembershipLevel":3,"AccountID":3799306,"AccountGuid":"650be5a5-a407-4c05-93c2-b4530ff6546e","Email":"","AvatarImage":"bb6a98c3-d78f-4355-b47f-a864be280cf6.jpg","GeocacheFindCount":1592,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":322161129,"CacheID":1997597,"LogGuid":"f6bc730d-c000-45cc-acac-ada380c52ff3","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zufallsfund <img src=\"/images/icons/icon_smile_big.gif\" border=\"0\" align=\"middle\" /><br />Eigentlich wollte ich zu einem anderen Cache in der Nähe, aber da lungerten einige Muggel herum. Auf dem Rückweg zum Auto fiel mir dieses interessante Objekt auf und ich wollte eigentlich nur ein paar Fotos schiessen, als ich plötzlich etwas auffälliges entdeckte, was sich als Tupperdose entpuppte. <img src=\"/images/icons/icon_smile_shock.gif\" border=\"0\" align=\"middle\" /><br />Glück muss man halt auch mal haben! <img src=\"/images/icons/icon_smile_clown.gif\" border=\"0\" align=\"middle\" /><br />Leider hab ich erst jetzt bemerkt, daß da wohl Bonusangaben im Cache waren. Schade eigentlich. <img src=\"/images/icons/icon_smile_blackeye.gif\" border=\"0\" align=\"middle\" />","Created":"2013-06-14","Visited":"2013-06-11","UserName":"Numanoid","MembershipLevel":3,"AccountID":4249410,"AccountGuid":"29c56639-491f-4617-b984-4f3b1092c69a","Email":"","AvatarImage":"739e7649-2cae-4b2e-a810-1b79d2560ed4.jpg","GeocacheFindCount":6830,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":321612660,"CacheID":1997597,"LogGuid":"6103c6af-65b5-4033-96bc-50b6e9a73df9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Ich bin ja nicht so oft in Hannover und da ist dieser Cache ja eher für mich ungeeignet. Aber im letzten Jahr besuchte ich Piratenbraut und da fingen wir das Ding einfach mal an. Bei einem späteren Besuch der Stadt machte ich allein weiter und dann traf ich auch mal einen alten Bekannten aus Sachsen in der Stadt. Vor 3 Wochen stand ich dann hilflos am Final und fand die Dose nicht. Das kann doch nicht sein. Also nochmal nachgefragt und bestätigt bekommen: Ja, Du bist richtig. Nun sollte die Sache endlich ein Ende finden. Hurra!<br />Danke für den Cache und Grüße<br /><font color=\"blue\"><b>tom</b>taucher</font>","Created":"2013-06-11","Visited":"2013-06-06","UserName":"tomtaucher","MembershipLevel":3,"AccountID":1130836,"AccountGuid":"d5062bf7-e9ba-4f92-b7c2-da2a9fe85b13","Email":"","AvatarImage":"d6602c2d-0930-42bf-9904-b907a4ddc7ab.jpg","GeocacheFindCount":7276,"GeocacheHideCount":53,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":317984786,"CacheID":1997597,"LogGuid":"66c56a78-b73c-40a0-93d1-b683ee673848","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"So! Endlich! Warum wir den nie angegangen sind wissen wir gar nicht. Der Start wurde ja gleich kurz nach Publish besucht. Und dann lag das Teil in der Mappe \"Mysteries noch zu besuchen\", und lag und lag und lag.<br />Bis heute. Stift und Meista haben es geschafft.<br />Schöner Cache bei dem wir unseren Spass hatten und deshalb auch ein blaues Schleifchen dalassen.<br /><br />danke von findenixe<br /><br />This entry was edited by findenixe on Tuesday, 28 May 2013 at 19:33:43 UTC.","Created":"2013-05-28","Visited":"2013-05-28","UserName":"findenixe","MembershipLevel":3,"AccountID":2527321,"AccountGuid":"95c7c5af-b10e-4978-88a3-97a6d34b6f8e","Email":"","AvatarImage":"d4b000d7-0171-45dd-b860-b5c66703bdab.jpg","GeocacheFindCount":3106,"GeocacheHideCount":17,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":317981966,"CacheID":1997597,"LogGuid":"c86bbe39-fc5c-4b20-a8b0-1326d86052b8","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Bei diesem Cache hatten mein Stift findenixe und ich eine Unterbrechung von fast zwei Jahren. <br />Immer wieder aufgeschoben und heute am ersten Tag nach dem großen Regen konnten wir uns im Logbuch verewigen. <br />Ein wirklich sehr schöner Mystery mit tollen Stationen. <br />Das schöne Erlebnis haben wir dann mit einem zünftigen Cocktail gebührend gefeiert. <br /><br />Vielen Dank für den schönen Cache <img src=\"/images/icons/icon_smile_approve.gif\" border=\"0\" align=\"middle\" /><br /><br />Beste Grüße <br /><br />wolkenreiter","Created":"2013-05-28","Visited":"2013-05-28","UserName":"wolkenreiter","MembershipLevel":3,"AccountID":2493686,"AccountGuid":"60f38281-1fd1-47ce-b5af-4c7e48af1a97","Email":"","AvatarImage":"db98af51-2b31-4845-b07f-c955ea36ff74.jpg","GeocacheFindCount":3123,"GeocacheHideCount":46,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":311243118,"CacheID":1997597,"LogGuid":"5a2842b9-6439-4be7-9981-33bcff242f52","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Mit Pimf und behindthewoods konnten wir hier unseren Logeintrag hinterlassen, Pimf berichtete schon von der Spontan Cache Runde. Ich persönlich finde die Idee und die Ausführung wirklich schön gelungen und freue mich jetzt noch mehr auf die folgenen Teile. Danke dafür sagt Klondike!","Created":"2013-05-04","Visited":"2013-05-03","UserName":"Klondike!","MembershipLevel":3,"AccountID":1881876,"AccountGuid":"5b54fc62-3aaf-4342-b9ff-56371737710e","Email":"","AvatarImage":"8c2a6d08-9a30-4495-b3af-82dd1d256f38.jpg","GeocacheFindCount":1481,"GeocacheHideCount":17,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":311086452,"CacheID":1997597,"LogGuid":"36470c2e-dfc8-4eea-9aa5-9b30cfdea581","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Das Rätsel war schon länger gelöst, aber irgendwie passten uns die Öffnungszeiten nie. Heute war es dann recht spontan soweit und wir machten uns im Team mit Pimf und Klondike! auf an die erste Station. Was für eine schöne Idee dachten wir immer wieder und fühlten uns an die guten alten \"Hannopoly-Zeiten\" erinnert. So gelangten wir dann auch recht zügig an das Final und konnten uns auf den Bonus freuen.","Created":"2013-05-04","Visited":"2013-05-03","UserName":"behindthewoods","MembershipLevel":3,"AccountID":1633965,"AccountGuid":"99ae935e-abae-4d46-94e3-92a2344d4d80","Email":"","AvatarImage":"8f31e629-540a-4826-a7f9-cc44c1ee411e.jpg","GeocacheFindCount":1435,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":311034899,"CacheID":1997597,"LogGuid":"9d56f8c2-5aa8-452a-be20-3057b0bd1cad","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Irgendwie wusste Klondike!, behindthewoods und ich nicht, welchen Cache wir heute machen wollen, und so entschieden wir uns spontan, diesen hier, der schon lange auf der to do-Liste stand, anzugehen. Mal sehen wie weit wir kommen...<br />Der Start war schon lange herausgerätselt, heute dann genau da hin, Aufgabe erfolgreich absolviert und weiter ging es. An der ersten ZS einmal außen rum, was uns schon etwas Zeit gekostet hat, aber das Wetter war schön, noch jemanden getroffen, kurzen Plausch gehalten, weiter ging´s zur ZS. Auf der Nahe gelegenen Bank nach ca. 3 Minuten die richtige Idee gehabt, jaaaa...passt.....und weiter geht´s.<br />Die nächste ZS versetzte mich in Erinnerung an die Hanopoly-Reihe, so macht cachen Spaß. Auch hier ging es gemeinsam schnell weiter und schon waren wir am Final. Alle Plätze hat man schon einmal besucht, aber natürlich mit einem anderen Blickwinkel. Dann schnell heimlich zugegriffen und das Logbuch signiert. In der Dose noch was vorgefunden - ahhhhha, ja das kennen wir doch! Wir haben nix besseres vor, also heute noch den Bonus erledigen.<br />DFDC<br />#1478","Created":"2013-05-04","Visited":"2013-05-03","UserName":"Pimf","MembershipLevel":3,"AccountID":3188002,"AccountGuid":"f86d97b1-c6ea-4fc1-839c-35ca83f55f45","Email":"","AvatarImage":"27983572-0e97-4b12-9e89-07772f42f024.jpg","GeocacheFindCount":1551,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":309790600,"CacheID":1997597,"LogGuid":"a13027ac-fafa-451c-b0b8-e32e3028e14d","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"... hier kam auch ohne fedora & bullwhip echtes indy-feeling auf ... wir müssen die filme unbedingt mal wieder ansehen!<br /><br />sehr schön ... wird gerne mit einer schleife belohnt. tftc<br />indy + marion<br /><br />PS: grüsse an anne-marie","Created":"2013-04-29","Visited":"2013-04-29","UserName":"s-m-w","MembershipLevel":3,"AccountID":3895182,"AccountGuid":"45a13381-0cfc-40f0-9b27-7de6f470ba3d","Email":"","AvatarImage":"80c774ed-d16c-45c2-a765-a8877eb085c5.jpg","GeocacheFindCount":726,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":309473308,"CacheID":1997597,"LogGuid":"002dfa28-b99b-4824-b6c3-9c253fc234bc","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Bereits im Sommer 2012 hatte ich gemeinsam mit 4engel und dem Schnatzfänger die Zwischenstationen absolviert, konnte aber an der Finalsuche nicht teilnehmen. Dies wurde nun heute nachgeholt. DFDC sagt die<br />Baumfee","Created":"2013-04-28","Visited":"2013-04-28","UserName":"Baumfee","MembershipLevel":3,"AccountID":2741970,"AccountGuid":"969ffa5f-93a4-44b6-bfdd-26c13b70f303","Email":"","AvatarImage":"bebd9991-f4a2-4f78-b1dd-93dd35654f4b.jpg","GeocacheFindCount":1289,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":318655060,"CacheID":1997597,"LogGuid":"43697e49-54dd-4671-83aa-ba9faf3f335d","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hier hat elbo mich heut mit her genommen.","Created":"2013-05-31","Visited":"2013-04-20","UserName":"j.mail","MembershipLevel":1,"AccountID":5421548,"AccountGuid":"c78fe637-a4c6-4487-9c70-c153c8979c4a","Email":"","AvatarImage":"d8b117c2-8432-4395-89c2-d10fe307b9c1.jpg","GeocacheFindCount":790,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":309732016,"CacheID":1997597,"LogGuid":"ab5d30e7-3a1e-4ad8-940a-34007b303c68","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute im Team endlich das Finale gefunden und diesen Cache abgeschlossen!<br /><br />tftc<br />Voiata","Created":"2013-04-29","Visited":"2013-04-20","UserName":"Voiata","MembershipLevel":3,"AccountID":3342573,"AccountGuid":"a3632b7c-446d-4bc7-bb92-142789d49ce5","Email":"","AvatarImage":"d2f47d26-e57f-450d-aef7-49bff328e30e.jpg","GeocacheFindCount":2328,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":309729437,"CacheID":1997597,"LogGuid":"1930cd9e-9197-41a8-9c87-1331f097ccc8","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schon lange Zeit waren wir hier dran und heute konnten wir endlich mal den Abschluss finden. Ein sehr schönes Ding, was einiges von uns abverlangt hat.<br /><br />Herzlichen Dank Meinerseits!<br /><br /># 3110","Created":"2013-04-29","Visited":"2013-04-20","UserName":"Dima9000","MembershipLevel":3,"AccountID":1469636,"AccountGuid":"fd739fd5-a24a-4ebe-9a07-27e647f0074a","Email":"","AvatarImage":"427dbb9c-f84d-4fa3-ac81-582af1d28052.png","GeocacheFindCount":3357,"GeocacheHideCount":14,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":307472888,"CacheID":1997597,"LogGuid":"84e83641-7747-48e0-a49e-ba527d1155c9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hier konnten wir heute im Team vorbeischauen und nach langen hin und her das Döschen dann doch noch finden.<br /><br />Danke dafür das gibt nen FAP","Created":"2013-04-20","Visited":"2013-04-20","UserName":"elbo","MembershipLevel":3,"AccountID":3021496,"AccountGuid":"93e761e2-f9b1-43dc-ac60-3d2e43a50418","Email":"","AvatarImage":"65f8d163-5700-4ca3-a309-a446d6e7c70f.jpg","GeocacheFindCount":4262,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":304943795,"CacheID":1997597,"LogGuid":"de2207f9-1a0a-4315-a853-c9ac0f16c75a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Was vor einem knappen Jahr begann, nahm nun ein glückliches Ende!<br />2 sonnige Mittagspausen verbrachte ich bereits am Ort der Schattenlinie. Eine 3. konnte abgewendet werden, als ich Cacherfreunden meine wüsten Notizen zeigte, denn sie bargen schon die Lösung. Wieso habe ich das nicht direkt gesehen?????<img src=\"/images/icons/icon_smile_blush.gif\" border=\"0\" align=\"middle\" /><br />Dann dauerte es wieder, bis es weiterging. Der letzte Teil wurde dann schrittweise fleißig erledigt.<br />Puh, und dann findet man da wieder was zum Knobeln... Hat man denn nie Ruhe?<img src=\"/images/icons/icon_smile_cool.gif\" border=\"0\" align=\"middle\" /><br />Vielen Dank für das facettenreiche Rätsel und die Dose.","Created":"2013-04-10","Visited":"2013-04-09","UserName":"YLaraY","MembershipLevel":3,"AccountID":3987450,"AccountGuid":"ac21e19d-aab7-465a-94d5-8923b11a0eec","Email":"","AvatarImage":"2011ff91-a2ed-46ff-9f95-93f4efb4b5aa.jpg","GeocacheFindCount":3068,"GeocacheHideCount":15,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 150, "rows": 150 } };
-var gaToken = 'UA-2020240-1';//]]>
+initalLogs = {"status":"success", "data": [{"LogID":485663443,"CacheID":1997597,"LogGuid":"af80ccaa-d904-41a0-9865-898c386870c8","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schon ewig stand dieser Cache auf meiner ToDoListe und selbst der Start war schon entschlüsselt, besucht und die nötigen Informationen eingesammelt! Doch wo war nur dieser verdammte Zettel mit den wichtigen Info´s geblieben! Gestern also zusammen mit Senfhan nochmals zum Start- lag ja immerhin fast auf dem Weg! Heute dann zusammen auf´s Radl geschwungen und den weiteren Hinweisen gefolgt! Hier hatte Senfhan als gebürtiger Hannoveraner doch tatsächlich mal den richtigen Riecher, da meine Wenigkeit nicht ganz so ortskundig ist, wie er! Und schwuppdiwupp standen wir schneller als erwartet am Final und waren doch ein wenig enttäuscht, dass das Abenteuer so schnell vorbei war! Aber Teil zwei wird bald folgen...<br /><br />nizole","Created":"2015-03-23","Visited":"2015-03-18","UserName":"nizole","MembershipLevel":3,"AccountID":1471652,"AccountGuid":"d14f7e45-aff1-4fd4-b9c7-839c5019e042","Email":"","AvatarImage":"f3cfc3aa-76f2-4221-864a-72629d3d0b92.jpg","GeocacheFindCount":2631,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":474047576,"CacheID":1997597,"LogGuid":"9b1b3f1b-ebb4-4080-9389-46d851154ce2","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute ging es mit dakar74, cumbaya und NWD auf die Spuren von Indianer Jones Die Stationen konnten gut gefunden und die gefundenen Hinweise schnell entschlüsselt werden, so das wir bereits nach ca. 1 Stunde überraschend am Final standen. Bei einem D5 hätte ich schon noch etwas mehr erwartet.<br /><br />Danke fürs legen und pflegen","Created":"2015-01-26","Visited":"2015-01-23","UserName":"jokar61","MembershipLevel":3,"AccountID":2827984,"AccountGuid":"b15acc18-7847-422d-b919-873770544d29","Email":"","AvatarImage":"9e7f655c-ce4a-4c87-a580-25f1f19f5102.jpg","GeocacheFindCount":1822,"GeocacheHideCount":6,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":474044973,"CacheID":1997597,"LogGuid":"6f6e1e3b-e80f-4860-9f67-3276c9bc0ce3","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Im Team mit Jokar61, Cumbaya und New World Disorder ging es heute auf , den Spuren von Indianer Jones zu folgen.<br />Der Start und die Stationen gingen gut von der Hand und schon nach etwas über 1 Std. hielten wir das Logbuch in der Hand .<br /><br />Für die Ideen hinterlasse ich gern ein Fav. Punkt <br /><br />DfdC","Created":"2015-01-26","Visited":"2015-01-23","UserName":"dakar74","MembershipLevel":3,"AccountID":7742897,"AccountGuid":"8ab4e972-df93-45ba-94b9-550a47c0c3a1","Email":"","AvatarImage":"","GeocacheFindCount":1552,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":473519970,"CacheID":1997597,"LogGuid":"bae55bad-b0db-4ad9-b9cb-a15b0dd68b56","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute sollte es im Team mit cumbaya, Jokar61 und Dakar74 losgehen um den Spuren des Indianer Jones zu folgen.<br />Wenn doch jede Schatzsuche so am schnürchen laufen, dann wären wir gemachte Leute <img src=\"/images/icons/icon_smile_big.gif\" border=\"0\" align=\"middle\" /><br />Gestern schnell das Listing überfolgen, sofort drängte sich die erste Idee für den Start in den Kopf. Schnell mal untereinander verglichen, passt so.<br />Heute dann auf zum Start. Da wir vlt. 5 Minuten zupät waren, hatten Dakar und Jokar Zeit sich alles schon einmal alleine anzuschauen. <br />Zeit die reichte das un ssofort bei der Ankuft eine passende Lösung präsentiert wurde die dann nur noch einmal kurz von allen auf plausiblität geprüft wurde.<br />ZS1 war schnell gefunden und der erste Blick auf die Hinweise verrit sofort was hier zu tun ist. Zielstrebig ging es zu ZS2. Während die eine Hälfte des Teams decodierte recherchierte die zweite Hälfte die mit den schon entschlüsselten Hinweisen so das die ZS3 nach kurzer Zeit enttarnt war.<br /><br />Wir waren sehr überrascht als wir hier dann schon das Final vorfanden.<br /><br />Die Art wie dieser Cache aufgebaut ist wirklich genial, das hat sehr gut gefallen. Wir hätten wirklich sehr gerne noch eine Hand voll Stationen in diesem Muste mehr abgearbeitet.<br />Vielleicht haben wir einfach Glück gehabt das wir immer gleich den riecher hatten, aber rückwirkend betrachtet ist sowohl D5, wie auch T3 hier etwas zu hoch angesiedelt.<br /><br />Eine Schleife lassen wir trotzdem da :)<br /><br />Date / Time : 23.01.2015 16:01:00<br />Count: 902<br />Day: Found 1 of 1 with 0 DNF<br /><br /><br />Danke für den Cache sagen<br /><br />Vincent Shezar & anima obscura<br /><br />New World Disorder<br />(Hin und wieder stehen wir auch mal als \"NWD\" im Logbuch, um Platz zu sparen, oder wenn es halt einfach mal schneller gehen muss)","Created":"2015-01-24","Visited":"2015-01-23","UserName":"New World Disorder","MembershipLevel":3,"AccountID":5412756,"AccountGuid":"ff83a8a9-95a6-4a3a-bff8-37ef16522000","Email":"","AvatarImage":"","GeocacheFindCount":969,"GeocacheHideCount":12,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":470444317,"CacheID":1997597,"LogGuid":"ba9a8f2e-7c62-44ab-9af3-c67b549655ae","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Diesen wollte ich mit dem Engel schon lange angehen, gestern war es dann soweit.Uns hatt alles gut gefallen. Im Dunkeln war es sogar ein bisschen gruselig. Vielen Dank dafür und ein Fav.","Created":"2015-01-05","Visited":"2015-01-04","UserName":"Engel und Fuchs","MembershipLevel":3,"AccountID":7794687,"AccountGuid":"8bf8cb9d-5fc7-4acc-b7a6-bda320b80875","Email":"","AvatarImage":"ac9cb33d-5c62-422f-9d6f-a77a7ca2f2da.jpg","GeocacheFindCount":2171,"GeocacheHideCount":16,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":470402389,"CacheID":1997597,"LogGuid":"b5398576-ba53-4ed5-b6d4-eef16b4cefda","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zusammen mit dem Fuchs wurden heute mal ein paar bereits gelöste Mysteries abgearbeitet. Die Vorarbeit war schon erledigt, nur das Final fehlte noch. Aber auch das konnte sich trotz Dunkelheit in diesem sehr passenden Ambiente nicht ewig vor uns verstecken. <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /><br />DFDC","Created":"2015-01-04","Visited":"2015-01-04","UserName":"Angel Ina","MembershipLevel":3,"AccountID":7515117,"AccountGuid":"45c7c989-cec4-4a7c-8676-a244357b543e","Email":"","AvatarImage":"500451a8-1863-4d5c-8743-2cfdf7d844cf.jpg","GeocacheFindCount":2001,"GeocacheHideCount":6,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":464874415,"CacheID":1997597,"LogGuid":"b3dfde97-6b38-4ce0-8086-32c94fd91351","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Am besten fanden wir hier den Start, zum Glück durch einen anderen Cache gewusst, wo die Schattenlinie zu finden ist. Die 1. Station haben wir dann nach einer Woche aufgesucht und konnten mit dem Hinweis vor Ort nicht so schnell etwas anfangen. Zu hause dann versucht es so zu lösen, bis endlich der Groschen viel und der nächste Ort aufgesucht wurde.<br />Wieder erst mal alles nur fotografiert und mit nach hause geschleppt.<br />Jetzt war es endlich soweit und wir konnten mit den ermittelten Sachen wieder starten.<br />War richtig unheimlich hier im Dunkeln, aber der Ort ist natürlich absolut perfekt. Schade, dass hier schon Schluß war! Von uns gibt es auf jeden Fall einen Favoritenpunkt, besonders für den Start.","Created":"2014-12-06","Visited":"2014-12-05","UserName":"flecki1","MembershipLevel":3,"AccountID":4110776,"AccountGuid":"31d92d97-022d-4238-8c2a-3c4fcf28d128","Email":"","AvatarImage":"480cfb25-3f69-494b-86b5-0212cb6e2b33.jpg","GeocacheFindCount":3804,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":463546602,"CacheID":1997597,"LogGuid":"6a99474e-2e5c-4359-9554-b8805c9f7543","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Anfangs hatte ich nie eine Ahnung, was das mit der Schattenlinie soll.<br />Anfang des Jahres stand ich plötzlich davor und erinnerte mich an den Cache.<br />Also hab ich gebastelt, bis ich die nötige Info auf passender Größe hatte...<br />aber was ich damit soll, war noch nicht ganz klar.<br />Heute wollte ich es dann spontan mal probieren, war erst etwas shoppen und<br />bin dann mit Sack und Pack hier vorbei gegangen.<br />Eine Touri-Gruppe später konnte ich dann loslegen und Indis Spuren folgen.<br />Naja, okay, es hat einen Augenblick gedauert, aber die Idee kam mir beim Lauschen der Infos.<br /><br />Das konnte ich dann schnell erledigen... hops und weiter...<br />Mit den nächsten Infos konnte ich erst nix anfangen... TJ?... Ja... oder doch nicht...<br />plötzlich ging mir ein Licht auf... ich hatte da was Wichtiges übersehen.<br />Also Standort wechseln... hier war ich letztens doch schonmal... und es ergab sich ein Sinn.<br />Hier und da noch etwas pfeilen und schon stand der nächste Reisepunkt auf meinem Navi.<br /><br />Auweia... hier war es bereits dunkel und die Beschreibung großzügig...<br />hab ich eine Chance? Ich gehe es mal logisch und mit Instinkt an...<br />und schwups war das erste Objekt auch schon meins.<br />Ein gekonnter Griff und da war die nächste Station?!<br />Nein... es war sogar schon das Final... schade, es hätte gern noch etwas weiter gehen können.<br />Coole Umsetzung der Thematik und Integration in die Umgebung.<br />DFDC","Created":"2014-11-27","Visited":"2014-11-27","UserName":"doko23","MembershipLevel":3,"AccountID":2310316,"AccountGuid":"a3811f7d-5ed4-42e3-a041-85385b4afef7","Email":"","AvatarImage":"06805d08-c8db-4edb-8134-9aa4628cb85f.jpg","GeocacheFindCount":4740,"GeocacheHideCount":15,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":459146512,"CacheID":1997597,"LogGuid":"d0075662-160c-4489-9d9b-3851a1d78d5f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Als der Bundescacheminister den Bonus von diesem Cache vorschlug, riefen Joersch und ich sofort ja. Da war nur eine noch eine Kleinigkeit zu erledigen... Achja, der Hauptcache. Den wollte ich schon eh lange gemacht haben, also los.<br />So machten wir uns auf die Spur von Station zu Station... Und freuten uns über nette kleine Rätsel, die wir gut im Team lösen konnten. Auch das letzte Hindernis konnte beseitigt werden und dann hielten wir die Dose in der Hand. Ganz ungefährlich ist es da zur Zeit nicht, mit den vielen Spritzen...<br /><br />Vielen Dank für die tollen Stationen und die Rätsel. Und danke natürlich auch an das Team. Es hat mal wieder Spaß gemacht. Daher verleihe ich gerne eine blaue Schleife :)","Created":"2014-11-04","Visited":"2014-11-01","UserName":"bountief","MembershipLevel":3,"AccountID":4581051,"AccountGuid":"7bb7e2da-c91b-48ec-8069-c1d12ff686c0","Email":"","AvatarImage":"c899db9a-00d3-499a-aa7d-fafdd5c14adc.jpg","GeocacheFindCount":1663,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":458386976,"CacheID":1997597,"LogGuid":"9f14da78-b3eb-4776-862b-0cfb47f4083a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Heute sollte es mal wieder ein T5 sein. Der Minister schlug den Bonus hiervon vor. Also müssen wir wohl erst mal hier ran. Also Lederpeitsche bunt Hut eingepackt und los gings! Ok, so schnell nicht, denn mich hielten am Vormittag noch andere Verpflichtungen auf. Somit ging es erst später als geplant los. Glücklicherweise reichte es noch und das Portal zur Station 2 war noch geöffnet. Bei ewiger Warterei auf auf ein koffeinhaltiges Heißgetränk hatten bountief und der Minister die Hinweise entschlüsselt und es ging weiter! Geschickt aufgeteilt wurde gesucht und bald hatte Schredder den richtigen Blick. Neben einer Menge Spritzen und anderem unappetitlichem Müll - konnte das Finale schnell gefunden werden. Auf ginge zum Bonus... Naja... fast... denn auch wir standen vor verschlossener Tür. Beim Bonus werden aktuell die Fledermäuse beschützt und bis Ende April wird das wohl nix... Vielleicht den Bonus so lange auch auf Schonzeit schicken... Vielen Dank für diesen Spaß und die sehr kreativen Stationen! So fühlt man sich wirklich wie Indiana Jones auf Expedition! Die blaue Schleife ist wohl verdient!","Created":"2014-11-02","Visited":"2014-11-01","UserName":"joersch","MembershipLevel":3,"AccountID":5251580,"AccountGuid":"7a53e877-213c-42a2-9e9b-313a2f8ff44f","Email":"","AvatarImage":"7f458db9-b8fd-4424-a42f-69f609bff6c7.jpg","GeocacheFindCount":1322,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":450404223,"CacheID":1997597,"LogGuid":"082e3eee-d639-410f-85db-1416b0f8f210","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Endlich sollte auch dieser Cache mal angegangen werden.<br />Besonders die Station 2 hat uns sehr gefallen, so etwas hatten wir bisher noch nie.<br />Alles in allem ein wirklich nett gemachter Cache, die Position der Finaldose jedoch gefiel uns gar nicht und ist auch der Grund hier keinen Fav.-Punkt zu geben.<br /><br />Vielen Dank!<br /><br />Team-Lorenz<br />Found: 713","Created":"2014-10-04","Visited":"2014-10-02","UserName":"Team-Lorenz","MembershipLevel":3,"AccountID":7300097,"AccountGuid":"9f7baed6-52e0-4d17-bd1f-3162963107c4","Email":"","AvatarImage":"66dfbf44-8dd1-4677-8cbf-a17f2fb8d51b.jpg","GeocacheFindCount":792,"GeocacheHideCount":14,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":462939856,"CacheID":1997597,"LogGuid":"74bea742-8b93-4553-bf9c-e4cdf1320735","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Das war mal echt was anderes. Die Örtlichkeiten und Rätsel haben mir so richtig gefallen, die Umstände um das Final jedoch nicht… passt auch eure Hände auf beim Suchen. So schwierig war es insgesamt dann doch nicht und so ging die ganze Runde gefühlt viel zu schnell vorbei.<br />Danke für die etwas andere Stadtführung, echt empfehlenswert <img src=\"/images/icons/icon_smile_big.gif\" border=\"0\" align=\"middle\" /><br /><br />littlefooty<br />","Created":"2014-11-23","Visited":"2014-09-29","UserName":"littlefooty","MembershipLevel":3,"AccountID":1996219,"AccountGuid":"049551c8-cdb6-4444-aa32-28431de8d056","Email":"","AvatarImage":"","GeocacheFindCount":462,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":445549767,"CacheID":1997597,"LogGuid":"c8019187-e03b-44c0-896a-80bf7b0e0ab9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Die Schattenlinie war mir schon lange bekannt, aber für das Abenteuer auf den Spuren von Henry Jones Junior hatte sich bis heute keine Gelegenheit ergeben. Nun war es endlich soweit und zusammen mit Clumsysheep konnten alle Stationen gut gefunden und relativ schnell gefunden werden. Die ganze Zeit fühlten wir uns, als seien wir wirklich in einem Indi-Abenteuer unterwegs, wobei ich froh war, dass ich nicht auch noch vorbeizischenden Kugeln und Explosionen ausweichen musste.<br /><br />Am Ende konnten wir die Welt retten und waren fast etwas enttäuscht, dass wir schon fertig waren.<br /><br />Vielen Dank für diesen außergewöhlichen Cache, den ich nur weiterempfehlen kann. Daher gibt es natürlich einen Favoritenpunkt.","Created":"2014-09-15","Visited":"2014-09-13","UserName":"CeKa82","MembershipLevel":3,"AccountID":4940226,"AccountGuid":"3d26d0b9-e0e3-4c2f-b6d3-7197de753557","Email":"","AvatarImage":"f0f3f858-afdb-4547-9599-4befc8304386.jpg","GeocacheFindCount":2661,"GeocacheHideCount":6,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":442726979,"CacheID":1997597,"LogGuid":"81aa275d-6eb9-4f65-aff6-61b6eb7ff75d","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zum Abschluss unseres Urlaubs stand dieser für heute auf dem Programm. Und was sollen wir sagen, von Beginn bis zum Eintrag ins Loggbuch haben wir uns in allen Belangen wie Indie gefühlt! Tolle Ideen, klasse Locations, schöne Knobeleien ! Da fehlten uns nur noch Lederhut und Peitsche... Gern mehr davon ! Den Fav. Haben wir gern dagelassen . DFDC!","Created":"2014-09-06","Visited":"2014-09-04","UserName":"Finde-Füchse","MembershipLevel":3,"AccountID":4068210,"AccountGuid":"0a52ce31-32d6-423d-847f-2f3d20ac5d67","Email":"","AvatarImage":"40f5cd25-b21b-4551-850a-d0cc24a70074.jpg","GeocacheFindCount":3169,"GeocacheHideCount":4,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":442257862,"CacheID":1997597,"LogGuid":"e4e3c30f-cf80-4d5a-956b-52238c69ea9d","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Wo die Schattenlinie zu finden sei, dass wussten wir schon lange, aber erst vor genau einem Monat kamen wir dazu, hier die Spur von Indianer Jones aufzunehmen. Aufgrund der Riesensause am Maschsee fanden wir nach der Weiterfahrt keinen passenden Abstellplatz für unser Expeditionsmobil und besuchten die nächste Station später, und da es ein Sonntag war, mussten wir eine weitere Pause einlegen. Heute recherchierten wir im angegebenen Zeitfenster und waren schnell wieder auf Kurs. Allerdings kam das Ende dann doch überraschender als gedacht ...<br /><br />Vielen Dank für den Cache!","Created":"2014-09-04","Visited":"2014-09-03","UserName":"2bupa","MembershipLevel":3,"AccountID":2675170,"AccountGuid":"e6a84779-ad63-4ba1-93fa-558a7190c8b4","Email":"","AvatarImage":"e30c21ec-8bce-4b90-9c6f-ee7e618da9fe.jpg","GeocacheFindCount":8744,"GeocacheHideCount":15,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":441250609,"CacheID":1997597,"LogGuid":"f73efee7-aabf-4cc1-9dab-eea4e349d983","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Irgendwie wirkte das Wetter heute nicht allzu vertrauenswürdig und so entschieden wir uns, statt einer Runde durch den Wald lieber durch die große Stadt zu laufen. <br /><br />Das Gleiche hatten wir letzte Woche auch schon getan und uns dabei an diesen Cache versucht. Nur zum Ende kamen wir nicht, es war dann einfach zu muggelig. Heute aber hatten wir mehr Glück, es war etwas ruhiger und wir konnten unser treiben etwas besser tarnen. <br /><br />So also geht ein wirklich toller Cache zu Ende, den wir so ganz ohne Hilfe wohl nicht geschafft hätten. Danke also an den Helfer ein fettes Danke mit blauer Schleife an den Owner!<br /><br />Bandit mit Colt<br /><br />This entry was edited by Bandit mit Colt on Wednesday, 10 September 2014 at 10:51:20 UTC.","Created":"2014-08-31","Visited":"2014-09-01","UserName":"Bandit mit Colt","MembershipLevel":3,"AccountID":5821212,"AccountGuid":"851cacb6-219d-477f-a64c-5ff51a337add","Email":"","AvatarImage":"7e2f9f3b-7f52-4819-ad99-7e9527bc430f.jpg","GeocacheFindCount":8046,"GeocacheHideCount":5,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":440401444,"CacheID":1997597,"LogGuid":"a18c32fc-5e55-462a-9ebb-f399dd5360c8","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Letzte Woche waren wir zufällig in Hannover und entschlossen uns spontan zu diesem Cache. Doch ohne Vorbereitung konnten wir nicht mal richtig starten. Allerdings lies uns das Listing nicht los und so begaben wir uns heute auf die Spur von Indiana Jones. Ohne zu Spoilern kann man leider kaum was schreiben... Dieser Cache ist wirklich der Hammer! Ein großes Lob an den Owner für diese Ideen und die Pflege. Wenn wir könnten, würden wir gleich mehrere Favoritenpunkte geben :-)","Created":"2014-08-29","Visited":"2014-08-29","UserName":"Traumsand","MembershipLevel":3,"AccountID":5557497,"AccountGuid":"b685432c-97ff-49ce-a63c-3019e78c55f5","Email":"","AvatarImage":"9f727299-67ba-4221-ac78-dbb9dcebe98d.jpg","GeocacheFindCount":885,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":434908333,"CacheID":1997597,"LogGuid":"fee322ec-e816-45aa-b492-b64d9d729d48","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Mit Hasenkeule und HWaii sind wir gemeinsam als Assistenten dem Indi gefolgt.<br />\r\nDas ist schon eine sehr schöne Kombination, mit minimalen Koordinatenangaben,<br />\r\ninteressante Orte in Hannover zu erkunden.<br />\r\nDie Idee mit der zeitbeschränkten Station ist genial.<br />\r\n<br />\r\nDer Bonus folgt... <img src=\"/images/icons/icon_smile_cool.gif\" border=\"0\" align=\"middle\" /><br />\r\n<br />\r\nVielen Dank für die versteckten , aber trotzdem öffentlichen Orte.<br />\r\n<br />\r\n<font color=\"blue\">ThomasAnderson<br />\r\n<br /></font>","Created":"2014-08-14","Visited":"2014-08-14","UserName":"ThomasAnderson","MembershipLevel":3,"AccountID":2280425,"AccountGuid":"47e2beb3-4a3d-4a8c-ba69-81d89560874c","Email":"","AvatarImage":"17cbfad4-4bbe-4c29-94b2-660b79ea51c6.jpg","GeocacheFindCount":939,"GeocacheHideCount":9,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":434846526,"CacheID":1997597,"LogGuid":"5e6d9c07-c7e7-4481-adf9-9342ce10c8e6","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"ThomasAnderson hat mich und H.Waii auf diesen Cache aufmerksam gemacht. Die gemeinsame Abarbeitung zog sich aber dann, weil die Stationen quasi einzeln abgearbeitet worden sind und Hannover Innenstadt nun doch nicht um die Ecke liegt.<br /><br />Schön gemachte Rätsel, die dem Indiana Jones-Geist gut Rechnung tragen. Insbesondere die Station mit der zeitlichen Beschränkung hat mir gefallen <img src=\"/images/icons/icon_smile_cool.gif\" border=\"0\" align=\"middle\" />. Ich war fast enttäuscht als ich die Final-Dose in den Händen hielt und keine weitere Aufgabe wartete...<br /><br />Danke für diese klasse Rätseljagd!!","Created":"2014-08-14","Visited":"2014-08-13","UserName":"Hasenkeule","MembershipLevel":3,"AccountID":4378965,"AccountGuid":"90af3caf-4b11-437c-b444-177a8f8fe099","Email":"","AvatarImage":"e94c7baf-0128-4e2e-b0a9-5c397548ac07.jpg","GeocacheFindCount":1842,"GeocacheHideCount":10,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":432346355,"CacheID":1997597,"LogGuid":"e119f3f4-a0b0-47cd-9cda-76b6750a9922","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Owner Maintenance","LogTypeImage":"46.png","LogText":"Mal nach den Stationen gesehen und Zettel aufgefüllt<br />Alles bestens<br />Viel Spass wünscht<br />Indi","Created":"2014-08-07","Visited":"2014-08-07","UserName":"indianerjones","MembershipLevel":3,"AccountID":678630,"AccountGuid":"af08f081-faf4-4992-8268-1e16ab4677a9","Email":"","AvatarImage":"3e670f19-793f-49d6-8832-564c4c886396.jpg","GeocacheFindCount":1061,"GeocacheHideCount":25,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":405505458,"CacheID":1997597,"LogGuid":"0a514baf-0f47-4471-b093-54ec183f6d9b","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Seinerzeit - zu Publishzeiten - waren wir noch so frisch im Geschäft, dass ein Cache mit dieser D/T-Wertung unerreichbar schien.<br />Inzwischen hat sich die Lage ja nun etwas geändert... Und als ich vor zwei Tagen am Start vorbei kam... denn wo der war, das war ja von Anfang an klar... Packte es mich dann. Also an drei Aufeinaderfolgenden Tagen die Stationen absolviert und vorhin glücklich geloggt.<br />Zwischendurch noch meine Großeltern besucht <img src=\"/images/icons/icon_smile_wink.gif\" border=\"0\" align=\"middle\" /> und an eine alte Stätte häufigen Aufenthalts zurückgekehrt. In die Anna Jooons....<br />Das war ne coole Tour!!<br /><br />TFTC sagt Mrs CMF<br /><br />IN:Fav","Created":"2014-05-08","Visited":"2014-05-08","UserName":"cookiemonsterfamily","MembershipLevel":3,"AccountID":2572906,"AccountGuid":"ec7c2430-4552-48d2-85f0-f031b8221c6a","Email":"","AvatarImage":"0822021c-d0e7-4eed-b32e-65457e8a8e78.jpg","GeocacheFindCount":7277,"GeocacheHideCount":28,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":402346295,"CacheID":1997597,"LogGuid":"bdea9c54-6610-43fc-995d-f302624eb1be","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Auf den Start schaue ich jeden Morgen aus dem Büro. Also vor längerer Zeit diesen Mysrery begonnen, aber immer wieder unterbrechen müssen. Mal fehlte das Team, mal waren die Zeiten unpassend. Heute nach einem kleinen Tipp diesen Cache beenden können. Wie auch die Vorlogger schon schrieben\"...leider schon vorbei....\". Dieser Cache war wirklich abenteuerlich und hat riesen Spass gemacht. Der Bonus ist als 200ster T5er geplant.<br /><br />Danke an den Owner für dieses außergewöhnliche Abenteuer und wir freuen uns schon auf die Fortsetzung<br /><br />DFDC sagen Charly.Maggy","Created":"2014-04-28","Visited":"2014-04-28","UserName":"Charly.Maggy","MembershipLevel":3,"AccountID":5286726,"AccountGuid":"bb95d7c1-7f17-4c30-83c7-b1914bfb888f","Email":"","AvatarImage":"cc557fd5-70a8-4136-8a59-e2318f2098f0.jpg","GeocacheFindCount":5948,"GeocacheHideCount":12,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":401181120,"CacheID":1997597,"LogGuid":"17ed5583-3c2b-4e37-9425-20e68140a742","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Schade, schon zu Ende <img src=\"/images/icons/icon_smile_dissapprove.gif\" border=\"0\" align=\"middle\" /><br /><br />Ich hätte gerne noch mehr Stationen von diesem Oberhammer gemacht.<br /><br />Alle Aufgaben und Stationen waren komplett stimmig zum Thema gestaltet. Wie andere auch schon geschrieben haben: da kommt Indianer Jones Feeling auf !<br /><br />Danke für diese tolle Reise mit anspruchsvollen Aufgaben, schicken Stationen und mega coolem Final. Dafür gibts natürlich ein Schleifchen und TFTC!","Created":"2014-04-25","Visited":"2014-04-25","UserName":"bube96","MembershipLevel":3,"AccountID":3930932,"AccountGuid":"fe928135-8705-44b4-859d-06e9bcff4f63","Email":"","AvatarImage":"19f1dea5-03ec-4983-9f2b-ee7aa562883c.png","GeocacheFindCount":1637,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":393730913,"CacheID":1997597,"LogGuid":"450624e5-8c1a-422b-b815-694cab36a110","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"OMG hat es ja schon ganz gut beschrieben. Nur: bei drei Cachern und zweimal Parken mit Gebühr, geht einer leer aus. Aber da wir sicher die Reihe weitermachen werden, wird es schon noch Gelegenheiten für mich geben, mein Geld in kleine Schlitze zu stecken.<br />Nach den leichten Startschwierigkeiten lief es dann wirklich gut. Das Wissen der einzelnen Teammitglieder fügte sich nahtlos zu einer Gesamtlösung zusammen. <br />Vielen Dank fürs Legen!<br />TFTC, Teletron (auf Tour mit sthl und OMG)<br /><br />PS: wo ist denn nur dieses blaue Schleifchen geblieben? Ach, hier.","Created":"2014-04-03","Visited":"2014-04-03","UserName":"Teletron","MembershipLevel":3,"AccountID":2480420,"AccountGuid":"1f222ea5-12e8-4def-86fe-5fbe2c8af2f4","Email":"","AvatarImage":"d03fd2b2-d2ec-4436-ad5a-712b3b154973.jpg","GeocacheFindCount":1602,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":393600249,"CacheID":1997597,"LogGuid":"5dac1383-e550-4ef2-8f3d-d73c88bcd4cf","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Was schreibt man hier am besten? Ich probieren es einfach mal...<br />Wir haben auf dieser Runde Sachen gesehen die für uns alle komplett neu waren. Am Start hatten wir Tomaten auf den Augen, zugegeben. Aber danach lief es, IMHO, recht flüssig. Alle Teammitglieder haben sich in die Lösungen und Parkgebühren geteilt,... fast ;-) <br />Mir persönlich hat die Prefinalstation am Besten gefallen. Der Oberhammer!<br />Aber auch der größte Spaß ist irgendwann vorbei und so standen wir mit verstörten Gesichtern am Final: \"Wie? Das war's schon?\" Leider.<br /><br />Ich freu mich schon auf die nächsten Herausforderungen im bewährten Team.<br /><br />TFTC OldManGrimm<br /><br />PS: Da ich mich ein wenig wie Indian(er/a) fühlen konnte bleibt ein Favo beim Prefinal...<br /><br />This entry was edited by OldManGrimm on Thursday, 03 April 2014 at 06:14:13 UTC.","Created":"2014-04-02","Visited":"2014-04-02","UserName":"OldManGrimm","MembershipLevel":3,"AccountID":389591,"AccountGuid":"95126b00-d716-4db8-a181-ff08dc31b03f","Email":"","AvatarImage":"47ccdb3d-bc92-4ff1-a853-c0f055d5c467.jpg","GeocacheFindCount":818,"GeocacheHideCount":4,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 195, "rows": 195 } };
+var gaToken = 'UA-2020240-1';ga('create', 'UA-2020240-35', 'geocaching.com'); ga('send', 'pageview');//]]>
</script>
</form>
- <script type="text/javascript">
+ <script src="/js/jquery_plugins/tinynav.min.js"></script>
+ <script src="/js/matchMedia.js"></script>
+ <script src="/account/scripts/custom/message-center-header-widget.js"></script>
+ <script>
+ $('#messagecenterheaderwidget').messageCenterHeaderWidget();
+
var browserType = {
IE: !!(window.attachEvent && !window.opera),
Opera: !!window.opera,
@@ -1235,18 +1053,57 @@ var gaToken = 'UA-2020240-1';//]]> MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};
+ // Modernizr only identifies browsers that support touch events; Windows Phone and webOS handle touch differently
+ var isMobile = (/(webOS|hpwOS|IEMobile)/).test(navigator.userAgent);
+
$(function () {
- // Make the menu system play nice with all browsers:
- $('ul.Menu li').hover(function () {
- $(this).addClass('hover');
- $('ul:first', this).css('visibility', 'visible');
- }, function () {
- $(this).removeClass('hover');
- $('ul:first', this).css('visibility', 'hidden');
+ var $topMenuLinks = $('.Menu > li');
+
+ $topMenuLinks.children('a').each(function () {
+ $(this).on('touchstart click', function (e) {
+ e.stopPropagation();
+
+ var $this = $(this),
+ $parent = $(this).parent();
+
+ $topMenuLinks.removeClass('hover');
+
+ if (!$parent.hasClass('hover') && $this.hasClass('Dropdown')) {
+ e.preventDefault();
+ $parent.addClass('hover');
+ }
+ });
});
- if (!isiOS()) {
- // Constructing a Twitter-esque Login:
- $(".SignInLink").click(function (e) {
+
+ var $userMenuBtn = $('.logged-in-user .li-user-toggle');
+
+ $userMenuBtn.on('touchstart click', function (e) {
+ e.stopPropagation();
+ $(this).next('ul').addClass('user-expanded');
+ });
+
+ $(document).on('click', function (e) {
+ if ($('.user-expanded').length && !$(e.target).parents().hasClass("user-expanded")) {
+ $('.user-expanded').removeClass("user-expanded");
+ }
+ if (!$(e.target).parents().hasClass("Menu")) {
+ $topMenuLinks.removeClass("hover");
+ }
+ });
+
+ if (isMobile || Modernizr.touch) {
+ // Convert language dropdown to native select
+ $("ul.language-list .selected").parent().addClass("selected");
+ $(".selected-language a, ul.language-list").hide();
+ $(".language-list").tinyNav({
+ active: 'selected'
+ });
+ }
+
+
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").on('click', function (e) {
+ if (window.matchMedia("(min-width: 1000px)").matches) {
e.preventDefault();
$("#SignInWidget").toggle();
$(".ProfileWidget").toggleClass("WidgetOpen");
@@ -1259,21 +1116,14 @@ var gaToken = 'UA-2020240-1';//]]> }
});
return false;
- });
- }
+ }
+ });
+
if (!("placeholder" in document.createElement("input"))) {
$("#SignInWidget label").removeClass("hideMe");
}
- $('.SignedInProfileLink').truncate({
- width: 120,
- after: '&hellip;',
- center: false,
- addclass: false,
- addtitle: false
- });
-
// Hide the warning message if the user closed it already
if ($.cookie('hide_warning') != null) {
$(".WarningMessage").hide();
@@ -1286,739 +1136,735 @@ var gaToken = 'UA-2020240-1';//]]> function isiOS() {
return (
- (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
- );
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
}
});
</script>
-
- <script type="text/javascript">
- <!--
-
- function s2gps(guid) {
- var w = window.open('/seek/sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no');
- w.focus();
- }
-
- function s2phone(wpid) {
- window.location.href='/seek/sendtophone.aspx?gc=' + wpid;
- }
-
- function pl(lc) {
- document.location.href='/seek/cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n');
- }
-
- function setNotification(id) {
- //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'});
- //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'});
- }
-
- function cmo(id) {
- Cookie.set('sn', true);
- }
-
- function pp(img) {
- var w = window.open(img);
- w.focus();
- }
-
- var map, bounds;
- var canUpdateFavoriteStatus = true;
- var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false;
- var logInitialLoaded = false;
- var $tfoot = $("#cache_logs_table").find("tfoot");
- var currentPageIdx = 1, totalPages = 1, pageSize = 10;
- var isBusy = false;
-
- var locString = {
- decrypt: 'Decrypt',
- encrypt: 'Encrypt'
- };
-
- $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle");
- $("#tmpl_CacheLogImages").template("tmplCacheLogImages");
- $("#tmpl_CacheLogRow").template("tmplCacheLogRow");
-
- $(".EncryptDecrypt")
- .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} })
- .click(function (e) {
- e.preventDefault();
- $("tr.log-row").each(function (i, obj) {
- var $obj = $(obj);
- if ($obj.data("encoded") == true) {
- var lt = $obj.find("p.LogText");
- //var ltDecoded = $('<div />').html(lt.html()).text();
- lt.html(convertROTStringWithBrackets(lt.html()));
- }
- });
-
- decryptLogs = !decryptLogs;
-
- $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
-
- return false;
- });
-
- function appendNewLogs(obj) {
-
- totalPages = obj.pageInfo.totalPages;
-
- var $newBody = $(document.createElement("TBODY"));
-
- $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody);
-
- $newBody.find("a.tb_images").each(function()
- {
- var $this = $(this);
- $this.fancybox({
- 'type': 'image',
- 'titlePosition': 'inside',
- 'padding': 10,
- titleFormat: function() { return $this.data('title'); }
- });
- });
-
- $("#cache_logs_table")
- .append($newBody.children());
-
- currentPageIdx = obj.pageInfo.idx + 1;
- pageSize = obj.pageInfo.size;
- }
+ + <script type="text/javascript"> + <!-- + + function s2gps(guid) { + var w = window.open('/seek/sendtogps.aspx?guid=' + guid, 's2gps', config='width=450,height=450,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,directories=no,status=no'); + w.focus(); + } + + function s2phone(wpid) { + window.location.href='/seek/sendtophone.aspx?gc=' + wpid; + } + + function pl(lc) { + document.location.href='/seek/cache_details_print.aspx?guid=' + guid + '&numlogs=' + lc +'&pt=full<=letter&decrypt='+ ((dh)?'y':'n'); + } + + function setNotification(id) { + //new Effect.Highlight(id, {startcolor:'#ffffff', endcolor:'#ffff99', restorecolor:'#ffff99', duration:3.0, queue:'front'}); + //new Effect.Highlight(id, {startcolor:'#ffff99', endcolor:'#ffffff', restorecolor:'#ffffff', duration:5.0, queue:'end'}); + } + + function cmo(id) { + Cookie.set('sn', true); + } + + function pp(img) { + var w = window.open(img); + w.focus(); + } + + var map, bounds; + var canUpdateFavoriteStatus = true; + var decryptLogs = (urlParams["decrypt"] && urlParams["decrypt"] == "y") ? true : false; + var logInitialLoaded = false; + var $tfoot = $("#cache_logs_table").find("tfoot"); + var currentPageIdx = 1, totalPages = 1, pageSize = 10; + var isBusy = false; + + var locString = { + decrypt: 'Decrypt', + encrypt: 'Encrypt' + }; + + $("#tmpl_CacheLogImagesTitle").template("tmplCacheLogImagesTitle"); + $("#tmpl_CacheLogImages").template("tmplCacheLogImages"); + $("#tmpl_CacheLogRow").template("tmplCacheLogRow"); + + $(".EncryptDecrypt") + .button({ icons: { secondary: 'ui-icon-arrowreturnthick-1-w'} }) + .click(function (e) { + e.preventDefault(); + $("tr.log-row").each(function (i, obj) { + var $obj = $(obj); + if ($obj.data("encoded") == true) { + var lt = $obj.find("p.LogText"); + //var ltDecoded = $('<div />').html(lt.html()).text(); + lt.html(convertROTStringWithBrackets(lt.html())); + } + }); + + decryptLogs = !decryptLogs; + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + return false; + }); + + function appendNewLogs(obj) { + + totalPages = obj.pageInfo.totalPages; + + var $newBody = $(document.createElement("TBODY")); + + $("#tmpl_CacheLogRow").tmpl(obj.data,{ includeAvatars: includeAvatars }).appendTo($newBody); + + $newBody.find("a.tb_images").each(function() + { + var $this = $(this); + $this.fancybox({ + 'type': 'image', + 'titlePosition': 'inside', + 'padding': 10, + titleFormat: function() { return $this.data('title'); } + }); + }); + + $("#cache_logs_table") + .append($newBody.children()); + + currentPageIdx = obj.pageInfo.idx + 1; + pageSize = obj.pageInfo.size; + } + + var showScroll = false; + + function callLogLoad(hideFooter) { + if (screen.width > 1090){ + showScroll = true; + } + $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs }, + function (response) { + if (response.status == "success") { + appendNewLogs(response); + if( hideFooter || (totalPages < currentPageIdx) ) { + $tfoot.hide(); + } + } else if (response.status == "error" && response.value == "1") { + // reload the page since the data had expired. + window.location.reload(); + } + isBusy = false; + }); + } + + $("#add_to_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv++; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr--; + $(".favorite-rank").text(fr); + + $("#pnlNonfavoriteCache").fadeOut("fast", function () { + $("#pnlFavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $("#remove_from_favorites").click(function () { + + if (canUpdateFavoriteStatus) { + canUpdateFavoriteStatus = false; + + var fv = parseInt($(".favorite-value").text()); + fv--; + $(".favorite-value").text(fv); + + var fr = parseInt($(".favorite-rank").text()); + fr++; + $(".favorite-rank").text(fr); + + $("#pnlFavoriteCache").fadeOut("fast", function () { + $("#pnlNonfavoriteCache").fadeIn("fast"); + }); + + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false', + success: function () { + canUpdateFavoriteStatus = true; + gotScore = false; + showFavoriteScore(); + } + }); + + return false; + } + }); + + $(function () { + + // CSP Section + if ($("#cspMessage").length) { + + var editLink = $('a[href*="report.aspx"]').attr('href'); + + $("#cspMessage").prepend('<P><strong>Already submitted this geocache?</strong> Please check below for the Reviewer’s notes and make any necessary changes before you resubmit. You can also respond by clicking "Log Your Visit" and posting a Reviewer Note.</P>'); + $("#cspMessage").prepend('<P>Your geocache has not been published. Once your geocache is in place and all of the details have been entered, click "Submit for Review". A volunteer reviewer will begin the review process within about 7 days.</P>'); + + $("#cspGoBack").click(function (e) { + e.preventDefault(); + window.location = editLink; + return false; + }); + + $("#cspSubmit").click(function (e) { + e.preventDefault(); + $.pageMethod("/seek/cache_details.aspx/EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + window.location = '/seek/cache_details.aspx?guid=' + r.guid; + } else { + alert("There was an error enabling your cache."); + } + }); + return false; + }); + + + } + + + //override coords + if (typeof(userDefinedCoords) != "undefined") { + if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + $("#uxLatLon") + .data("isOverridden", true) + .addClass("myLatLon"); + } else if (userDefinedCoords.status == "success") { + mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data); + } else { + $("#uxLatLonLink").contents().unwrap(); + } + } else { + $("#uxLatLonLink").contents().unwrap(); + } + + + var cacheNoteText = { + DefaultText: 'Click to enter a note', + ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.', + SavingText: 'Please wait, saving your note...' + }; + + + + $("time.timeago").timeago(); + + $(".button").button(); + + var sn = Cookie.get('sn'); + + if ($('#trNotPM').length > 0) { + $('#trNotPM').toggle(!sn); + } + + $("#cache_note").editInPlace({ + callback: function (unused, enteredText) { + var me = $(this); + + var et = $.trim(enteredText); + if (et.length > 500 ) { + et = et.substr(0, 500); + } + $.pageMethod("/seek/cache_details.aspx/SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) { + var r = JSON.parse(r.d); + if (r.success == true) { + if ($.trim(r.note) == "") { + $("#cache_note").text(cacheNoteText.DefaultText); + } else { + $("#cache_note").text(r.note); + } + + me.effect('highlight', { color: '#ffb84c' }, 'slow'); + } else { + alert(cacheNoteText.ErrorInSaving); + $("#cache_note").text(cacheNoteText.DefaultText); + } + + }); + + return cacheNoteText.SavingText; + } + , default_text: cacheNoteText.DefaultText + , field_type: "textarea" + , textarea_rows: "7" + , textarea_cols: "65" + , show_buttons: true + , bg_over: "#dad7cb" + //, callback_skip_dom_reset: true + + }); + + $("#lnk_slippyMap").click(function(e) { + e.preventDefault(); + loadDynamicMap(); + return false; + }); + + $(".inplace_field").live("focus", function () { + if ($(this).data("created") == null) { + $(this).data("created", true) + $(this).countable({ + maxLength: 500 + }); + } + }); + + $("#pcn_help").qtip({ + content: 'Enter your own notes here. No other user will be able to access them.', + position: { + my: 'top center', + at: 'bottom center' + }, + style: { + classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip' + }, + }); + + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); + + if ($("#cache_logs_container").length > 0) { + + appendNewLogs(initalLogs); + + if (DetectMobileQuick()) { + $("#pnlButtonLoad") + .show() + .find("a.MobileButton") + .click(function (e) { + e.preventDefault(); + callLogLoad(false); + return false; + }) + .button(); + if(!DetectTierTablet()){ + $("a.MobileButton").addClass("Phone"); + } + } else { + $("#pnlLazyLoad").show(); + + $(window).endlessScroll({ + fireOnce: true, + fireDelay: 500, + bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50, + ceaseFire: function(){ + // stop the scrolling if the last page is reached. + return (isLoggedIn == false) || (totalPages < currentPageIdx); + }, + callback: function() { + if (!isBusy) { + + isBusy = true; + $tfoot.show(); + callLogLoad(true); + } + } + }); + } + } + + if (!isLoggedIn) { + $("#cache_logs_table").find("tfoot").hide(); + } + + if (mapLatLng != null) { + + $("#uxLatLonLink").qtip({ + suppress:false, + content: buildCacheCoordMenu(), + position: { + my: 'left top', + at: 'right top', + adjust: { + x: 10, y: -10 + } + }, + show: { + ready: false, + event: "click", + solo: true + }, hide: { + event: 'unfocus' + }, + style: { + tip: { + corner: false + }, + classes: 'ui-tooltip-widget' + }, + events: { + show: function () { + if ($("#uxLatLon").data("isOverridden")) { + $("a.ccu-restore").show(); + } else { + $("a.ccu-restore").hide(); + } + + if (userDefinedCoords.status != "success") { + $("div.ccu-update").hide(); + } else { + $("div.ccu-update").show(); + } + } + } + }).click(function (e) { + e.preventDefault(); + return false; + }); + + $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({ + overlayShow: false + }); + + setStaticMaps(); + } + }); + + function setStaticMaps() { + + var map = new L.Map('map_preview_canvas', { + center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), + zoom: 10, + doubleClickZoom: false, + dragging: false, + touchZoom: false, + scrollWheelZoom: false, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })); + + var mapLarge = L.map('map_canvas', { + center: [mapLatLng.lat, mapLatLng.lng], + zoom: 14, + doubleClickZoom: true, + dragging: true, + touchZoom: false, + scrollWheelZoom: false, + zoomControl: true, + attributionControl: false + }) + .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })) + .addControl(new L.Control.Scale()); + + var tileOptions = { + tileUrl: "https://otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg", + //name: "mpqosm", + //alt: "MapQuest", + subdomains: "1234", + //tileSize: 256, + minZoom: 0, + maxZoom: 18 + }; + + map.addLayer(L.tileLayer(tileOptions.tileUrl, tileOptions)); + + L.tileLayer(tileOptions.tileUrl, tileOptions) + .addTo(mapLarge); + + var pinIcon = L.Icon.extend({ + iconSize: new L.Point(20, 23), + iconAnchor: new L.Point(10,23), + shadowUrl: null + }); + + var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), + { + icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}), + title: mapLatLng.name + }) + .on("click", function () { + document.getElementById("uxlrgMap").scrollIntoView(true); + return false; + }); + + L.marker([mapLatLng.lat, mapLatLng.lng], { + icon: L.icon({iconUrl: '/images/wpttypes/pins/' + mapLatLng.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23]}), + clickable: false, + //zIndexOffset: 99, + title: mapLatLng.name + }).addTo(mapLarge); + + map.addLayer(mkA); + + if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) { + + var llBounds = L.latLngBounds([mapLatLng.lat, mapLatLng.lng], [mapLatLng.lat, mapLatLng.lng]); + + for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) { + + var item = cmapAdditionalWaypoints[x], + ll = [item.lat, item.lng]; + + L.marker(ll, { + icon: L.icon({ iconUrl: '/images/wpttypes/pins/'+ item.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23] }), + title: item.name, + clickable: false + }).addTo(mapLarge); + + llBounds.extend(ll); + } + + window.setTimeout(function () { + mapLarge.fitBounds(llBounds.pad(.5)); + }, 100); + + } + } + + var lnkDH = $('#ctl00_ContentBody_lnkDH'); + function dht() { + try { + $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html())); + var linkText = ((lnkDH.attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt'); + lnkDH + .text(linkText) + .attr('title', linkText); + } catch (e) { + alert(e); + return false; + } + return false; + } + + function buildCacheCoordMenu() { + var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng) + $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" ); + + var $menu = $("<div></div>"); + + $( "#tmpl_CacheCoordinateUpdate" ).tmpl( { + ll: [mapLatLng.lat, mapLatLng.lng], + ll_formatted: mapLatLng.oldLatLngDisplay + } ).appendTo( $menu ); + + $menu.find("button.ccu-button").button(); + + $menu.delegate("button.ccu-parse", "click", function (e) { + e.preventDefault(); + var $this = $(e.target), + $parse =$this.closest('dd').find(".cc-parse-text"), + parseCoords = $.trim($parse.val()); + + if (parseCoords.length == 0) { + alert('Please provide valid coordinates.'); + } else { + $.getJSON("/api/geocode", { parse: parseCoords}, function (response) { + if (response.status == "success") { + var newLatLng = new LatLon(response.data.lat, response.data.lng); + + // update the displayed coords + var dist = curLatLng.rhumbDistanceTo(newLatLng); + var bearingTo = curLatLng.rhumbBearingTo(newLatLng); + var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N"; + + var formats = response.data.formats; + // all these finds, make me feel dirty + $menu + .find("span.ccu-parseverify-coords").text(formats.DM).end() + .find("dl.ccu-parse").hide().end() + .find("dl.ccu-parseverify").show().end() + .find("button.ccu-parseverify-accept") + .data("utm", '') + .data("dm", formats.DM) + .data("lat", response.data.lat) + .data("lng", response.data.lng) + .end(); + } else { + alert("Sorry unable to parse the coordinates you entered."); + } + }); + } + + return false; + }); + + $menu.delegate("button.ccu-parseverify-accept", "click", function (e) { + e.preventDefault(); + var $this = $(this); + // update to webmethod + $.pageMethod("/seek/cache_details.aspx/SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } else { + $("#uxLatLonLink").qtip('hide'); + } + + }); + + return false; + }); + + $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) { + e.preventDefault(); + $menu + .find("input.cc-parse-text").val('').end() + .find("dl.ccu-parse").show().end() + .find("dl.ccu-parseverify").hide().end(); + return false; + }); + + $menu.delegate("a.ccu-restore", "click", function (e) { + e.preventDefault(); + + $.pageMethod("/seek/cache_details.aspx/ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) { + var r = JSON.parse(r.d); + if (r.status == "success") { + window.location.reload(); + } + }); + + return false; + }); + + return $menu; + } + + GSPK = window.GSPK || {}; + GSPK.Selector = {}; + GSPK.Selector.getSelected = function(){ + var t = null; + if ( window.getSelection ){ + t = window.getSelection(); + }else if(document.getSelection){ + t = document.getSelection(); + }else if(document.selection){ + t = document.selection.createRange().text; + } + return t; + } + //--> + </script> + <script id="loc_favPointsScoreDesc" type="text/html"> + Favorites/Premium Logs + </script> + <script type="text/javascript" language="javascript"> + <!-- + var gotScore = false; + var favDropDown = $('.favorite-dropdown'); + var favContainer = $('.favorite-container'); + + function showFavoriteScore() { + $('#imgFavoriteScore').attr('src', '/images/loading3.gif'); + + $('#uxFavoriteScore').parent().fadeTo(200, .001, function () { + $.ajax({ + type: "POST", + cache: false, + url: '/datastore/favorites.svc/score?u=' + userToken, + success: function (scoreResult) { + gotScore = true; + + var score = 0; + + if(scoreResult) { + score = scoreResult; + } + + if(score > 100) { + score = 100; + } + + $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png'); + var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim(); + $('#imgFavoriteScore').attr('alt', pieDesc); + $('#imgFavoriteScore').attr('title', pieDesc); + + $('#uxFavoriteScore').parent().fadeTo(1000, 1); + $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html()); + } + }); + }); + } + var scrollId = false, + logTop = 0; + + if (document.getElementById("cache_logs_container") != null){ + logTop = $("#cache_logs_container").position().top; + } + + + $(window).on("scroll", function() { + if (scrollId != false) { + window.clearTimeout(scrollId); + scrollId = false; + } + + scrollId = window.setTimeout(function() { + if (showScroll){ + if ($(this).scrollTop()< logTop) { + $("#topScroll").fadeOut(); + } else { + $("#topScroll").fadeIn(); + } + }}, 250); + }); + + $(document).bind('mouseup', function (e) { + var $clicked = $(e.target); + if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) { + favDropDown.hide(1, function () { + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + }); + } + }); + + $('#uxFavContainerLink').click(function () { + if ($(favDropDown).is(':visible')) { + favDropDown.hide(1, function(){ + favContainer.addClass('favorite-container'); + favContainer.removeClass('favorite-container-open'); + }); + } + else { + if (!gotScore) { + showFavoriteScore(); + } + + favContainer.addClass('favorite-container-open'); + favContainer.removeClass('favorite-container'); + favDropDown.show(1); + } + }); + + // End --> + </script> - var showScroll = false;
-
- function callLogLoad(hideFooter) {
- if (screen.width > 1090){
- showScroll = true;
- }
- $.getJSON("/seek/geocache.logbook", { tkn: userToken, idx: currentPageIdx, num: pageSize, decrypt: decryptLogs },
- function (response) {
- if (response.status == "success") {
- appendNewLogs(response);
- if( hideFooter || (totalPages < currentPageIdx) ) {
- $tfoot.hide();
- }
- } else if (response.status == "error" && response.value == "1") {
- // reload the page since the data had expired.
- window.location.reload();
- }
- isBusy = false;
- });
- }
-
- $("#add_to_favorites").click(function () {
-
- if (canUpdateFavoriteStatus) {
- canUpdateFavoriteStatus = false;
-
- var fv = parseInt($(".favorite-value").text());
- fv++;
- $(".favorite-value").text(fv);
-
- var fr = parseInt($(".favorite-rank").text());
- fr--;
- $(".favorite-rank").text(fr);
-
- $("#pnlNonfavoriteCache").fadeOut("fast", function () {
- $("#pnlFavoriteCache").fadeIn("fast");
- });
-
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/update?u=' + userToken + '&f=true',
- success: function () {
- canUpdateFavoriteStatus = true;
- gotScore = false;
- showFavoriteScore();
- }
- });
- return false;
- }
- });
-
- $("#remove_from_favorites").click(function () {
-
- if (canUpdateFavoriteStatus) {
- canUpdateFavoriteStatus = false;
-
- var fv = parseInt($(".favorite-value").text());
- fv--;
- $(".favorite-value").text(fv);
-
- var fr = parseInt($(".favorite-rank").text());
- fr++;
- $(".favorite-rank").text(fr);
-
- $("#pnlFavoriteCache").fadeOut("fast", function () {
- $("#pnlNonfavoriteCache").fadeIn("fast");
- });
-
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/update?u=' + userToken + '&f=false',
- success: function () {
- canUpdateFavoriteStatus = true;
- gotScore = false;
- showFavoriteScore();
- }
- });
-
- return false;
- }
- });
-
- $(function () {
-
- // CSP Section
- if ($("#cspMessage").length) {
-
- var editLink = $('a[href*="report.aspx"]').attr('href');
-
- $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>');
- $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>');
- $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>');
-
- $("#cspGoBack").click(function (e) {
- e.preventDefault();
- window.location = editLink;
- return false;
- });
-
- $("#cspSubmit").click(function (e) {
- e.preventDefault();
- $.pageMethod("/seek/cache_details.aspx/EnableCSPCache", JSON.stringify({ dto: { ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.success == true) {
- window.location = '/seek/cache_details.aspx?guid=' + r.guid;
- } else {
- alert("There was an error enabling your cache.");
- }
- });
- return false;
- });
-
- $("#cspConfirm").change(function() {
- if ($("#cspConfirm").is(":checked")) {
- $("#cspSubmit").removeAttr('disabled');
- $("#cspGoBack").attr('disabled', true);
- } else {
- $("#cspSubmit").attr('disabled', true);
- $("#cspGoBack").removeAttr('disabled');
- }
- });
- }
-
-
- //override coords
- if (typeof(userDefinedCoords) != "undefined") {
- if (userDefinedCoords.status == "success" && userDefinedCoords.data.isUserDefined == true) {
- mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
- $("#uxLatLon")
- .data("isOverridden", true)
- .addClass("myLatLon");
- } else if (userDefinedCoords.status == "success") {
- mapLatLng = $.extend({}, mapLatLng, userDefinedCoords.data);
- } else {
- $("#uxLatLonLink").contents().unwrap();
- }
- } else {
- $("#uxLatLonLink").contents().unwrap();
- }
-
-
- var cacheNoteText = {
- DefaultText: 'Click to enter a note',
- ErrorInSaving: 'There was an error saving page. Please refresh the page and try again.',
- SavingText: 'Please wait, saving your note...'
- };
-
-
-
- $("time.timeago").timeago();
-
- $(".button").button();
-
- var sn = Cookie.get('sn');
-
- if ($('#trNotPM').length > 0) {
- $('#trNotPM').toggle(!sn);
- }
-
- $("#cache_note").editInPlace({
- callback: function (unused, enteredText) {
- var me = $(this);
-
- var et = $.trim(enteredText);
- if (et.length > 500 ) {
- et = et.substr(0, 500);
- }
- $.pageMethod("/seek/cache_details.aspx/SetUserCacheNote", JSON.stringify({ dto: { et: et, ut: userToken} }), function (r) {
- var r = JSON.parse(r.d);
- if (r.success == true) {
- if ($.trim(r.note) == "") {
- $("#cache_note").text(cacheNoteText.DefaultText);
- } else {
- $("#cache_note").text(r.note);
- }
-
- me.effect('highlight', { color: '#ffb84c' }, 'slow');
- } else {
- alert(cacheNoteText.ErrorInSaving);
- $("#cache_note").text(cacheNoteText.DefaultText);
- }
-
- });
-
- return cacheNoteText.SavingText;
- }
- , default_text: cacheNoteText.DefaultText
- , field_type: "textarea"
- , textarea_rows: "7"
- , textarea_cols: "65"
- , show_buttons: true
- , bg_over: "#dad7cb"
- //, callback_skip_dom_reset: true
-
- });
-
- $("#lnk_slippyMap").click(function(e) {
- e.preventDefault();
- loadDynamicMap();
- return false;
- });
-
- $(".inplace_field").live("focus", function () {
- if ($(this).data("created") == null) {
- $(this).data("created", true)
- $(this).countable({
- maxLength: 500
- });
- }
- });
-
- $("#pcn_help").qtip({
- content: 'Enter your own notes here. No other user will be able to access them.',
- position: {
- my: 'top center',
- at: 'bottom center'
- },
- style: {
- classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip'
- },
- });
- $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt);
-
- if ($("#cache_logs_container").length > 0) {
-
- appendNewLogs(initalLogs);
-
- if (DetectMobileQuick()) {
- $("#pnlButtonLoad")
- .show()
- .find("a.MobileButton")
- .click(function (e) {
- e.preventDefault();
- callLogLoad(false);
- return false;
- })
- .button();
- if(!DetectTierTablet()){
- $("a.MobileButton").addClass("Phone");
- }
- } else {
- $("#pnlLazyLoad").show();
-
- $(window).endlessScroll({
- fireOnce: true,
- fireDelay: 500,
- bottomPixels: ($(document).height() - $("#cache_logs_container").offset().top) + 50,
- ceaseFire: function(){
- // stop the scrolling if the last page is reached.
- return (isLoggedIn == false) || (totalPages < currentPageIdx);
- },
- callback: function() {
- if (!isBusy) {
-
- isBusy = true;
- $tfoot.show();
- callLogLoad(true);
- }
- }
- });
- }
- }
-
- if (!isLoggedIn) {
- $("#cache_logs_table").find("tfoot").hide();
- }
-
- if (mapLatLng != null) {
-
- $("#uxLatLonLink").qtip({
- suppress:false,
- content: buildCacheCoordMenu(),
- position: {
- my: 'left top',
- at: 'right top',
- adjust: {
- x: 10, y: -10
- }
- },
- show: {
- ready: false,
- event: "click",
- solo: true
- }, hide: {
- event: 'unfocus'
- },
- style: {
- tip: {
- corner: false
- },
- classes: 'ui-tooltip-widget'
- },
- events: {
- show: function () {
- if ($("#uxLatLon").data("isOverridden")) {
- $("a.ccu-restore").show();
- } else {
- $("a.ccu-restore").hide();
- }
-
- if (userDefinedCoords.status != "success") {
- $("div.ccu-update").hide();
- } else {
- $("div.ccu-update").show();
- }
- }
- }
- }).click(function (e) {
- e.preventDefault();
- return false;
- });
-
- setStaticMaps();
- //$("#staticMap").lazyload();
- }
- });
-
- function setStaticMaps() {
- var llBounds = new L.LatLngBounds();
-
- var map = new L.Map('map_preview_canvas', {
- center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- zoom: 10,
- doubleClickZoom: false,
- dragging: false,
- touchZoom: false,
- scrollWheelZoom: false,
- attributionControl: false
- })
- .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }));
-
- var mapLarge = new L.Map('map_canvas', {
- center: new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- zoom: 14,
- doubleClickZoom: true,
- dragging: true,
- touchZoom: false,
- scrollWheelZoom: false,
- zoomControl: true,
- attributionControl: false
- })
- .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' }))
- .addControl(new L.Control.Scale());
-
- llBounds.extend(new L.LatLng(mapLatLng.lat, mapLatLng.lng));
-
- var tileOptions = {
- tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg",
- name: "mpqosm",
- alt: "MapQuest",
- //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ",
- subdomains: "1234",
- tileSize: 256,
- minZoom: 0,
- maxZoom: 18
- };
-
- map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
- mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions));
-
- var pinIcon = L.Icon.extend({
- iconSize: new L.Point(20, 23),
- iconAnchor: new L.Point(10,23),
- shadowUrl: null
- });
-
- var mkA = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng),
- {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
- title: mapLatLng.name
- })
- .on("click", function () {
- document.getElementById("uxlrgMap").scrollIntoView(true);
- return false;
- });
-
- var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}),
- clickable: false, zIndexOffset:99, title: mapLatLng.name
- });
-
- map.addLayer(mkA);
- mapLarge.addLayer(mkA2);
-
- $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({
- overlayShow: false
- });
-
- if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) {
-
- for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) {
-
- var item = cmapAdditionalWaypoints[x],
- ll = new L.LatLng(item.lat, item.lng),
- marker = new L.Marker(ll, {
- icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}),
- title: item.name,
- clickable:false
- });
-
- llBounds.extend(ll);
- mapLarge.addLayer(marker);
- }
- var bz = mapLarge.getBoundsZoom(llBounds.pad(1.1));
-
- mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz);
- }
- }
-
- var lnkDH = $('#ctl00_ContentBody_lnkDH');
- function dht() {
- try {
- $('#div_hint').html(convertROTStringWithBrackets($('#div_hint').html()));
- var linkText = ((lnkDH.attr('title') == 'Decrypt') ? 'Encrypt' : 'Decrypt');
- lnkDH
- .text(linkText)
- .attr('title', linkText);
- } catch (e) {
- alert(e);
- return false;
- }
- return false;
- }
-
- function buildCacheCoordMenu() {
- var curLatLng = new LatLon(mapLatLng.lat, mapLatLng.lng)
- $.template( "tmplCacheCoordinateUpdate_CoordItem", "<tr><td nowrap='nowrap'>${t}</td><td class='ccc-coord' nowrap='nowrap' dataum='${k}'>${v}</td></tr>" );
-
- var $menu = $("<div></div>");
-
- $( "#tmpl_CacheCoordinateUpdate" ).tmpl( {
- ll: [mapLatLng.lat, mapLatLng.lng],
- ll_formatted: mapLatLng.oldLatLngDisplay
- } ).appendTo( $menu );
-
- $menu.find("button.ccu-button").button();
-
- $menu.delegate("button.ccu-parse", "click", function (e) {
- e.preventDefault();
- var $this = $(e.target),
- $parse =$this.closest('dd').find(".cc-parse-text"),
- parseCoords = $.trim($parse.val());
-
- if (parseCoords.length == 0) {
- alert('Please provide valid coordinates.');
- } else {
- $.getJSON("/api/geocode", { parse: parseCoords}, function (response) {
- if (response.status == "success") {
- var newLatLng = new LatLon(response.data.lat, response.data.lng);
-
- // update the displayed coords
- var dist = curLatLng.rhumbDistanceTo(newLatLng);
- var bearingTo = curLatLng.rhumbBearingTo(newLatLng);
- var bearing = bearingTo >= 0 || bearingTo < 22.5 ? "N" : bearingTo >= 22.5 || bearingTo < 67.5 ? "NE" : bearingTo >= 67.5 || bearingTo < 112.5 ? "E" : bearingTo >= 112.5 || bearingTo < 157.5 ? "SE" : bearingTo >= 157.5 || bearingTo < 202.5 ? "S" : bearingTo >= 202.5 || bearingTo < 247.5 ? "SW" : bearingTo >= 247.5 || bearingTo < 292.5 ? "W" : bearingTo >= 292.5 || bearingTo < 337.5 ? "NW" : "N";
-
- var formats = response.data.formats;
- // all these finds, make me feel dirty
- $menu
- .find("span.ccu-parseverify-coords").text(formats.DM).end()
- .find("dl.ccu-parse").hide().end()
- .find("dl.ccu-parseverify").show().end()
- .find("button.ccu-parseverify-accept")
- .data("utm", '')
- .data("dm", formats.DM)
- .data("lat", response.data.lat)
- .data("lng", response.data.lng)
- .end();
- } else {
- alert("Sorry unable to parse the coordinates you entered.");
- }
- });
- }
-
- return false;
- });
-
- $menu.delegate("button.ccu-parseverify-accept", "click", function (e) {
- e.preventDefault();
- var $this = $(this);
- // update to webmethod
- $.pageMethod("/seek/cache_details.aspx/SetUserCoordinate", JSON.stringify({ dto: { data: {lat: $this.data("lat"), lng: $this.data("lng") }, ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.status == "success") {
- window.location.reload();
- } else {
- $("#uxLatLonLink").qtip('hide');
- }
-
- });
-
- return false;
- });
-
- $menu.delegate("button.ccu-parseverify-cancel", "click", function (e) {
- e.preventDefault();
- $menu
- .find("input.cc-parse-text").val('').end()
- .find("dl.ccu-parse").show().end()
- .find("dl.ccu-parseverify").hide().end();
- return false;
- });
-
- $menu.delegate("a.ccu-restore", "click", function (e) {
- e.preventDefault();
-
- $.pageMethod("/seek/cache_details.aspx/ResetUserCoordinate", JSON.stringify({ dto: { ut: userToken } }), function (r) {
- var r = JSON.parse(r.d);
- if (r.status == "success") {
- window.location.reload();
- }
- });
-
- return false;
- });
-
- return $menu;
- }
-
- GSPK = window.GSPK || {};
- GSPK.Selector = {};
- GSPK.Selector.getSelected = function(){
- var t = null;
- if ( window.getSelection ){
- t = window.getSelection();
- }else if(document.getSelection){
- t = document.getSelection();
- }else if(document.selection){
- t = document.selection.createRange().text;
- }
- return t;
- }
- //-->
- </script>
- <script id="loc_favPointsScoreDesc" type="text/html">
- Favorites/Premium Logs
- </script>
- <script type="text/javascript" language="javascript">
- <!--
- var gotScore = false;
- var favDropDown = $('.favorite-dropdown');
- var favContainer = $('.favorite-container');
-
- function showFavoriteScore() {
- $('#imgFavoriteScore').attr('src', '/images/loading3.gif');
-
- $('#uxFavoriteScore').parent().fadeTo(200, .001, function () {
- $.ajax({
- type: "POST",
- cache: false,
- url: '/datastore/favorites.svc/score?u=' + userToken,
- success: function (scoreResult) {
- gotScore = true;
-
- var score = 0;
-
- if(scoreResult)
- score = scoreResult;
-
- if(score > 100)
- score = 100;
-
- $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png');
- var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim();
- $('#imgFavoriteScore').attr('alt', pieDesc);
- $('#imgFavoriteScore').attr('title', pieDesc);
-
- $('#uxFavoriteScore').parent().fadeTo(1000, 1);
- $('#uxFavoriteScore').html('<strong>' + (score < 1 ? "<1" : score) + '%</strong> ' + $("#loc_favPointsScoreDesc").html());
- }
- });
- });
- }
- var scrollId = false,
- logTop = $("#cache_logs_container").position().top;
- $(window).on("scroll", function() {
- if (scrollId != false) {
- window.clearTimeout(scrollId);
- scrollId = false;
- }
-
- scrollId = window.setTimeout(function() {
- if (showScroll){
- if ($(this).scrollTop()< logTop) {
- $("#topScroll").fadeOut();
- } else {
- $("#topScroll").fadeIn();
- }
- }}, 250);
- });
-
- $(document).bind('mouseup', function (e) {
- var $clicked = $(e.target);
- if (!$clicked.parents().hasClass("favorite-dropdown") && !$clicked.parents().hasClass("FavoriteWidget")) {
- favDropDown.hide(1, function () {
- favContainer.addClass('favorite-container');
- favContainer.removeClass('favorite-container-open');
- });
- }
- if ($('#log-dropdown-options').is(':visible') && !$clicked.parents().hasClass('Dropdown')){
- $('#log-dropdown-options').toggleClass('hideMe');
- $('.Dropdown').toggleClass('Active');
- }
- });
-
- $('#uxFavContainerLink').click(function () {
- if ($(favDropDown).is(':visible')) {
- favDropDown.hide(1, function(){
- favContainer.addClass('favorite-container');
- favContainer.removeClass('favorite-container-open');
- });
- }
- else {
- if (!gotScore) {
- showFavoriteScore();
- }
+ <script type="text/javascript">
- favContainer.addClass('favorite-container-open');
- favContainer.removeClass('favorite-container');
- favDropDown.show(1);
- }
- });
- $('#dropdown-arrow').on('click', function(e){
- e.preventDefault();
- $('#log-dropdown-options').toggleClass('hideMe');
- $('.Dropdown').toggleClass('Active');
- });
- // End -->
- </script>
-
- <script type="text/javascript">
$(document).ready(function () {
$('#hlUpgrade').bind('click', function () {
var _this = $(this);
@@ -2029,52 +1875,45 @@ var gaToken = 'UA-2020240-1';//]]> return false;
});
});
- </script>
- <script type="text/javascript">
+
+
+ _gaq.push(['_setCustomVar', 1, 'AccountId', 3409138, 1]);
+
+
_gaq.push(['_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js']);
_gaq.push(['_setAccount', gaToken]);
_gaq.push(['_trackPageview']);
- (function () {
- var ga = document.createElement('script');
- ga.src = ('https:' == document.location.protocol ?
- 'https://ssl' : 'http://www') +
- '.google-analytics.com/ga.js';
- ga.setAttribute('async', 'true');
- document.documentElement.firstChild.appendChild(ga);
- })();
+
$(function () {
$("a.language").click(function (e) {
e.preventDefault();
window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
});
});
- </script>
- <!-- Quantcast Tag -->
- <div id="Quantcast">
- <script type="text/javascript">
- var _qevents = _qevents || [];
- (function () {
- var elem = document.createElement('script');
+ var _qevents = _qevents || [];
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
- elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
- elem.async = true;
- elem.type = "text/javascript";
- var scpt = document.getElementsByTagName('script')[0];
- scpt.parentNode.insertBefore(elem, scpt);
- })();
- </script>
- <script type="text/javascript">
- _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
- </script>
- <noscript>
- <div style="display: none;">
- <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
- alt="Quantcast" />
- </div>
- </noscript>
- </div>
- <!-- End Quantcast tag -->
- <!-- Server: WEB17; Build: Web.HotFix_20130821.1 -->
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+
+
+
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" />
+ </div>
+ </noscript>
+ <!-- Server: WEB07; Build: Tucson.Main.release-20150330.1.Release_270
+ -->
</body>
</html>
diff --git a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java index a1337cd..77f078b 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java +++ b/tests/src/cgeo/geocaching/test/mock/GC2JVEH.java @@ -6,7 +6,9 @@ import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; + +import org.eclipse.jdt.annotation.NonNull; import java.text.ParseException; import java.util.ArrayList; @@ -56,11 +58,13 @@ public class GC2JVEH extends MockedCache { return "indianerjones, der merlyn,reflektordetektor"; } + @NonNull @Override public String getOwnerUserId() { return "indianerjones"; } + @NonNull @Override public CacheSize getSize() { return CacheSize.SMALL; @@ -89,13 +93,14 @@ public class GC2JVEH extends MockedCache { @Override public Date getHiddenDate() { try { - return GCLogin.parseGcCustomDate("28/11/2010", getDateFormat()); + return GCLogin.parseGcCustomDate("2010-11-28", getDateFormat()); } catch (ParseException e) { // intentionally left blank } return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { diff --git a/tests/src/cgeo/geocaching/test/mock/GC3XX5J.html b/tests/src/cgeo/geocaching/test/mock/GC3XX5J.html index 44420e5..21d7e10 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC3XX5J.html +++ b/tests/src/cgeo/geocaching/test/mock/GC3XX5J.html @@ -1,50 +1,64 @@ - - -<!DOCTYPE html> -<html lang="en" class="no-js"> -<head id="ctl00_Head1"><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><title> - GC3XX5J ZaraÅ¡Äen Tir (Traditional Cache) in Slovenia created by David & Ajda -</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta name="author" content="Groundspeak, Inc." /><meta name="DC.creator" content="Groundspeak, Inc." /><meta name="Copyright" content="Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2013 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/reset.css" /><link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/src/typography.css" /><link rel="stylesheet" type="text/css" media="screen,projection" href="../css/blueprint/src/grid.css" /> - <!--[if lt IE 8]> - <link rel="stylesheet" type="text/css" media="all" href="../css/blueprint/ie.css" /> - <![endif]--> - <link id="uxCssMaster" rel="stylesheet" type="text/css" media="screen,projection" href="../css/tlnMasterScreen.css?r=1" /><link id="uxCssMain" rel="stylesheet" type="text/css" media="all" href="../css/tlnMain.css?r=1" /><link rel="Stylesheet" type="text/css" media="all" href="../css/jqueryui1810/jquery-ui-1.8.10.custom.css" /><link rel="stylesheet" type="text/css" media="all" href="/js/jquery_plugins/jquery.jgrowl.css" /><link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" /> - <script type="text/javascript"> - var _gaq = _gaq || []; - </script> - <script type="text/javascript" src="/js/modernizr-1.7.min.js"></script> - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> - - <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js" type="text/javascript"></script> - <script type="text/javascript" src="/js/jquery.truncate.min.js"></script> - - <script type='text/javascript'> - var googletag = googletag || {}; - googletag.cmd = googletag.cmd || []; - (function () { - var gads = document.createElement('script'); - gads.async = true; - gads.type = 'text/javascript'; - var useSSL = 'https:' == document.location.protocol; - gads.src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js'; - var node = document.getElementsByTagName('script')[0]; - node.parentNode.insertBefore(gads, node); - })(); - </script> - - +
+
+<!DOCTYPE html>
+<html lang="en" class="no-js">
+<head id="ctl00_Head1"><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><title>
+ GC3XX5J ZaraÅ¡Äen Tir (Traditional Cache) in Slovenia created by David & Ajda
+</title><meta name="DC.title" content="Geocaching - The Official Global GPS Cache Hunt Site" /><meta id="ctl00_ogUrl" property="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC3XX5J&title=zarascen-tir" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="Geocaching: the anytime, anywhere outdoor adventure game." /><meta name="twitter:description" content="There are millions of geocaches worldwide and probably even some near you right now. Visit Geocaching.com to see just how many geocaches are nearby and to get the free Official Geocaching app." /><meta name="twitter:image:src" content="https://www.geocaching.com/play/Content/images/preview-lg.jpg" /><meta name="author" content="Geocaching" /><meta name="DC.creator" content="Geocaching" /><meta name="Copyright" content="Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved." /><!-- Copyright (c) 2000-2015 Groundspeak, Inc. All Rights Reserved. --><meta name="description" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta name="DC.subject" content="Geocaching is a treasure hunting game where you use a GPS to hide and seek containers with other participants in the activity. Geocaching.com is the listing service for geocaches around the world." /><meta http-equiv="imagetoolbar" content="no" /><meta name="distribution" content="global" /><meta name="MSSmartTagsPreventParsing" content="true" /><meta name="rating" content="general" /><meta name="revisit-after" content="1 days" /><meta name="robots" content="all" /><meta name="p:domain_verify" content="107f8f596a30ff1ea307df82db696a5e" /><link href="//fonts.googleapis.com/css?family=Noto+Sans:400,700&subset=latin,latin-ext" rel="stylesheet" type="text/css" /><link rel="icon" href="/favicon.ico" /><link rel="shortcut icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link href="/content/coreCSS?v=LW0HKwsIsnIiQyE_ovDSvnj5M2xR0XjkVV3GaTHUlRI1" rel="stylesheet"/>
+<link href="/css/jqueryui1104/jqUI?v=G2XN-0HsvYJqSZehzmbzhJiIBnEZ9PaVHVjIweqiSx41" rel="stylesheet"/>
+<link rel="stylesheet" type="text/css" media="print" href="../css/tlnMasterPrint.css" /><script src="/bundle/modernizer?v=q--nrqGQx_uxNYSvw1AFPQRWLPih7RGk2o0lu9veYaY1"></script>
+<script src="/bundle/coreJS?v=uKjd3XRiFC1C29gkUc0JuDRCF6PuUu7R8PpzGjgXDEc1"></script>
+
+
+ <script type="text/javascript">
+
+ var googletag = googletag || {};
+ googletag.cmd = googletag.cmd || [];
+
+ var _gaq = _gaq || [];
+
+ (function () {
+ var gads = document.createElement('script');
+ gads.async = true;
+ gads.type = 'text/javascript';
+ var useSSL = 'https:' == document.location.protocol;
+ gads.src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js';
+ var node = document.getElementsByTagName('script')[0];
+ node.parentNode.insertBefore(gads, node);
+ })();
+
+ (function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments);
+ }, i[r].l = 1 * new Date();
+ a = s.createElement(o),
+ m = s.getElementsByTagName(o)[0];
+ a.async = 1; a.src = g;
+ m.parentNode.insertBefore(a, m);
+ })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
+
+ (function () {
+
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') +
+ '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+
+ })();
+
+ </script>
+
+ <link href="/css/fancybox/jquery.fancybox.css" rel="stylesheet" type="text/css" /> <link href="/js/jquery_plugins/icalendar/jquery.icalendar.css" rel="stylesheet" type="text/css" /> <link href="/js/jquery_plugins/qtip/jquery.qtip.css" rel="stylesheet" type="text/css" /> - <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.css" /> - <!--[if IE]> - <link rel="stylesheet" type="text/css" media="all" href="/js/leaflet/0.5.1/leaflet.ie.css" /> - <![endif]--> + <link rel="stylesheet" type="text/css" media="all" href="/static/js/leaflet/0.7.2/leaflet.css" /> <link rel="stylesheet" type="text/css" media="screen" href="/css/seek/beta.css" /> - <script type="text/javascript" src="/js/leaflet/0.5.1/leaflet.js"></script> - <script type="text/javascript" src="/js/geometa.js"></script> + <script type="text/javascript" src="/static/js/leaflet/0.7.2/leaflet.js"></script> <script type="text/javascript"> var userToken = null, urlParams = {}, @@ -63,314 +77,215 @@ } })(); </script> -<meta name="og:site_name" content="Geocaching.com" property="og:site_name" /><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:url" content="http://www.geocaching.com/seek/cache_details.aspx?wp=GC3XX5J&title=zarascen-tir&Submit6=Go" property="og:url" /><meta name="og:description" content="Use a smartphone or GPS device to navigate to the provided coordinates. Look for a small hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 2 and difficulty is 1.5 (out of 5)." property="og:description" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/2.png" property="og:image" /><meta name="og:title" content="ZaraÅ¡Äen Tir" property="og:title" /><script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="description" content="ZaraÅ¡Äen Tir (GC3XX5J) was created by David & Ajda on 10/01/2012. It's a Small size geocache, with difficulty of 1.5, terrain of 2. It's located in Slovenia.Kadar zbolimo nam pomaga...When we get sick, they are helpful... SLO:tir je danes zapuÅ¡Äen, vÄasih pa so ga uporabljala razliÄna podjetja, da so po njem dostavljali material in odvažali konÄne izdelke." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=51e40dec-6272-4dad-934b-e175daaac265" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head> -<body background="https://lh6.googleusercontent.com/-PoDn9PmtYmg/UGnOZLEQboI/AAAAAAAAAHM/hBXxerWnSdA/s254/lek-verovskova.jpg" class="CacheDetailsPage"> - <form name="aspnetForm" method="post" action="/geocache/GC3XX5J_zarascen-tir?Submit6=Go" id="aspnetForm"> -<div> -<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> -<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> -<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" /> -<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE1Mzk0NTE5MTEPFgIeBEMuSUQoKVlTeXN0ZW0uSW50NjQsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQczMjIwNjcyFgJmD2QWBmYPZBYKAgYPFgIeBFRleHQFYjxtZXRhIG5hbWU9IkNvcHlyaWdodCIgY29udGVudD0iQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4iIC8+ZAIHDxYCHwEFRzwhLS0gQ29weXJpZ2h0IChjKSAyMDAwLTIwMTMgR3JvdW5kc3BlYWssIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC4gLS0+ZAIZDxYCHgRocmVmBR1+L2Nzcy90bG5NYXN0ZXJTY3JlZW4uY3NzP3I9MWQCGg8WAh8CBRV+L2Nzcy90bG5NYWluLmNzcz9yPTFkAh8PFgIeB1Zpc2libGVoZAIBDxYCHgZhY3Rpb24FKS9nZW9jYWNoZS9HQzNYWDVKX3phcmFzY2VuLXRpcj9TdWJtaXQ2PUdvFhYCCw8WAh8BZGQCDQ9kFgICBQ8WAh8DZxYIAgEPDxYCHghJbWFnZVVybAVOaHR0cDovL2ltZy5nZW9jYWNoaW5nLmNvbS91c2VyL2F2YXRhci9lOGE5N2EwNS1hMDUxLTRkYTktYmM5My02YTgzMGI4NjZhZmYuanBnZGQCAw8WAh8BBWxIZWxsbywgPGEgaHJlZj0iL215L2RlZmF1bHQuYXNweCIgdGl0bGU9IlZpZXcgUHJvZmlsZSBmb3IgSm9TYU1hSmEiIGNsYXNzPSJTaWduZWRJblByb2ZpbGVMaW5rIj5Kb1NhTWFKYTwvYT5kAgUPDxYCHgtOYXZpZ2F0ZVVybAWsAWh0dHBzOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2xvZ2luL2RlZmF1bHQuYXNweD9SRVNFVD1ZJnJlZGlyPWh0dHAlM2ElMmYlMmZ3d3cuZ2VvY2FjaGluZy5jb20lMmZzZWVrJTJmY2FjaGVfZGV0YWlscy5hc3B4JTNmd3AlM2RHQzNYWDVKJTI2dGl0bGUlM2R6YXJhc2Nlbi10aXIlMjZTdWJtaXQ2JTNkR29kZAILDxYCHwEFEDQ4NCBDYWNoZXMgRm91bmRkAhcPFgIfA2cWAgINDw8WAh8GBUB+L3RyYWNrL3NlYXJjaC5hc3B4P289MSZ1aWQ9NGQ0MTY0NjEtZDFhNy00Y2M1LThlZTctMzM2YmI5MTBmZWI4ZGQCHQ8PFgIfA2dkZAIpDxYCHwNnZAJXD2QWBAIDDxYCHwEFB0VuZ2xpc2hkAgUPFgIeC18hSXRlbUNvdW50AhQWKGYPZBYCAgEPDxYIHg9Db21tYW5kQXJndW1lbnQFBWVuLVVTHgtDb21tYW5kTmFtZQUNU2V0VGVtcExvY2FsZR8BBQdFbmdsaXNoHhBDYXVzZXNWYWxpZGF0aW9uaGRkAgEPZBYCAgEPDxYIHwgFBWRlLURFHwkFDVNldFRlbXBMb2NhbGUfAQUHRGV1dHNjaB8KaGRkAgIPZBYCAgEPDxYIHwgFBWZyLUZSHwkFDVNldFRlbXBMb2NhbGUfAQUJRnJhbsOnYWlzHwpoZGQCAw9kFgICAQ8PFggfCAUFcHQtUFQfCQUNU2V0VGVtcExvY2FsZR8BBQpQb3J0dWd1w6pzHwpoZGQCBA9kFgICAQ8PFggfCAUFY3MtQ1ofCQUNU2V0VGVtcExvY2FsZR8BBQnEjGXFoXRpbmEfCmhkZAIFD2QWAgIBDw8WCB8IBQVkYS1ESx8JBQ1TZXRUZW1wTG9jYWxlHwEFBURhbnNrHwpoZGQCBg9kFgICAQ8PFggfCAUFc3YtU0UfCQUNU2V0VGVtcExvY2FsZR8BBQdTdmVuc2thHwpoZGQCBw9kFgICAQ8PFggfCAUFZXMtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQhFc3Bhw7FvbB8KaGRkAggPZBYCAgEPDxYIHwgFBWV0LUVFHwkFDVNldFRlbXBMb2NhbGUfAQUFRWVzdGkfCmhkZAIJD2QWAgIBDw8WCB8IBQVpdC1JVB8JBQ1TZXRUZW1wTG9jYWxlHwEFCEl0YWxpYW5vHwpoZGQCCg9kFgICAQ8PFggfCAUFZWwtR1IfCQUNU2V0VGVtcExvY2FsZR8BBRDOlc67zrvOt869zrnOus6sHwpoZGQCCw9kFgICAQ8PFggfCAUFbHYtTFYfCQUNU2V0VGVtcExvY2FsZR8BBQlMYXR2aWXFoXUfCmhkZAIMD2QWAgIBDw8WCB8IBQVubC1OTB8JBQ1TZXRUZW1wTG9jYWxlHwEFCk5lZGVybGFuZHMfCmhkZAIND2QWAgIBDw8WCB8IBQVjYS1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0NhdGFsw6AfCmhkZAIOD2QWAgIBDw8WCB8IBQVwbC1QTB8JBQ1TZXRUZW1wTG9jYWxlHwEFBlBvbHNraR8KaGRkAg8PZBYCAgEPDxYIHwgFBW5iLU5PHwkFDVNldFRlbXBMb2NhbGUfAQUOTm9yc2ssIEJva23DpWwfCmhkZAIQD2QWAgIBDw8WCB8IBQVrby1LUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCe2VnOq1reyWtB8KaGRkAhEPZBYCAgEPDxYIHwgFBWh1LUhVHwkFDVNldFRlbXBMb2NhbGUfAQUGTWFneWFyHwpoZGQCEg9kFgICAQ8PFggfCAUFcm8tUk8fCQUNU2V0VGVtcExvY2FsZR8BBQhSb23Dom7Egx8KaGRkAhMPZBYCAgEPDxYIHwgFBWphLUpQHwkFDVNldFRlbXBMb2NhbGUfAQUJ5pel5pys6KqeHwpoZGQCWw9kFgICAw8WAh8DaGQCXQ8WAh4FY2xhc3MFDHNwYW4tMjQgbGFzdBYCAgEPZBYmAgEPZBYCZg9kFgICAQ8PFgIfAQUHR0MzWFg1SmRkAgIPFgIfAQWmATxhIGhyZWY9Ii9hYm91dC9jYWNoZV90eXBlcy5hc3B4IiB0YXJnZXQ9Il9ibGFuayIgdGl0bGU9IkFib3V0IENhY2hlIFR5cGVzIj48aW1nIHNyYz0iL2ltYWdlcy9XcHRUeXBlcy8yLmdpZiIgYWx0PSJUcmFkaXRpb25hbCBDYWNoZSIgdGl0bGU9IlRyYWRpdGlvbmFsIENhY2hlIiAvPjwvYT5kAgYPZBYEAgEPFgIfA2dkAgcPFgIfA2hkAgoPZBYGAgEPFgIfAQUBMWQCBQ8WAh8DaGQCBw8PFgIfBgVEL3NlZWsvY2FjaGVfZmF2b3JpdGVkLmFzcHg/Z3VpZD01MWU0MGRlYy02MjcyLTRkYWQtOTM0Yi1lMTc1ZGFhYWMyNjVkZAIMDw8WAh8DaGRkAg8PFgIfA2hkAhAPFgIfA2hkAhEPZBYMAgMPZBYCAgEPFgIfAQUbVVRNOiAzM1QgRSA0NjEzNDAgTiA1MTAzMTA5ZAINDw8WAh8GBTNjZHBmLmFzcHg/Z3VpZD01MWU0MGRlYy02MjcyLTRkYWQtOTM0Yi1lMTc1ZGFhYWMyNjVkZAIPDw8WAh8GBThjZHBmLmFzcHg/Z3VpZD01MWU0MGRlYy02MjcyLTRkYWQtOTM0Yi1lMTc1ZGFhYWMyNjUmbGM9NWRkAhEPDxYCHwYFOWNkcGYuYXNweD9ndWlkPTUxZTQwZGVjLTYyNzItNGRhZC05MzRiLWUxNzVkYWFhYzI2NSZsYz0xMGRkAhMPDxYEHwYFemh0dHA6Ly9tYXBzLmdvb2dsZS5jb20vbWFwcz9mPWQmaGw9ZW4mc2FkZHI9NTIuMjE2MjUsOS43MTQ0ODMgKEhvbWUgTG9jYXRpb24pJmRhZGRyPTQ2LjA4MDQ2NywxNC41KFphcmElYzUlYTElYzQlOGRlbitUaXIpHgZUYXJnZXQFBl9ibGFua2RkAhsPZBYIZg8PFgQeCUZvcmVDb2xvcgweBF8hU0ICBGRkAgEPDxYEHw0MHw4CBGRkAgIPDxYCHwNnFgIeB29uY2xpY2sFO3MyZ3BzKCc1MWU0MGRlYy02MjcyLTRkYWQtOTM0Yi1lMTc1ZGFhYWMyNjUnKTtyZXR1cm4gZmFsc2U7ZAIDDw8WAh8DZxYCHw8FIHMycGhvbmUoJ0dDM1hYNUonKTtyZXR1cm4gZmFsc2U7ZAITDxYCHwNnZAIXD2QWCGYPFgIfA2hkAgEPDxYCHwNoZGQCAg8PFgIfA2hkZAIDDxYCHwNoZAIYD2QWAgIDDw8WAh8BBQdEZWNyeXB0ZGQCGQ8WAh8BBUJCcXpueGF2IHhuenJhIGJvIGd2ZWggLyBFcnpiaXIgZ3VyIGZnYmFyIGp2cHUgeXZyZiBvcmZ2cXIgZ3VyIGVudnlkAhsPZBYEAgEPFgQfAgUfL3NlZWsvbG9nLmFzcHg/SUQ9MzIyMDY3MiZsY249MR4JaW5uZXJodG1sBQ5Mb2cgeW91ciB2aXNpdGQCAg8WAh8DaGQCHA8WAh8DZ2QCHQ8WAh8DaGQCIA9kFgICAw8WAh8QBRNBZHZlcnRpc2luZyB3aXRoIFVzZAIkD2QWBAIFDw8WAh8DZ2RkAgkPDxYCHwYFPH4vdHJhY2svc2VhcmNoLmFzcHg/d2lkPTUxZTQwZGVjLTYyNzItNGRhZC05MzRiLWUxNzVkYWFhYzI2NWRkAiYPDxYCHwNnZBYCZg8WAh8HAgEWAgIBD2QWAmYPFQIA3QE8YSBocmVmPSJodHRwOi8vd3d3Lmdlb2NhY2hpbmcuY29tL2Jvb2ttYXJrcy92aWV3LmFzcHg/Z3VpZD0xNDU1MTcwOC0wYzNjLTRmOTUtOTM0Mi0xYmIzMTE5ZTZlZmUiPmNnZW8gbW9ja3M8L2E+PGJyIC8+IGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2VvY2FjaGluZy5jb20vcHJvZmlsZS8/Z3VpZD00ZDQxNjQ2MS1kMWE3LTRjYzUt" /> -<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="OGVlNy0zMzZiYjkxMGZlYjgiPkpvU2FNYUphPC9hPmQCJw9kFhICAQ8PFgIfA2hkZAIDD2QWAgIBDw8WAh8GBUUvaGlkZS93cHRsaXN0LmFzcHg/UmVmV3B0SUQ9NTFlNDBkZWMtNjI3Mi00ZGFkLTkzNGItZTE3NWRhYWFjMjY1JkRTPTFkZAIHDw8WBh4GUkRTLklECyl2R3JvdW5kc3BlYWsuV2ViLkdQWC5XcHREYXRhU291cmNlcywgVHVjc29uLkNvbW1vbi5MZWdhY3ksIFZlcnNpb249My4wLjQ5ODEuMTMyOTMsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAEeB1JXUFQuSUQoKwQHMzIyMDY3Mh8DaGRkAgkPDxYCHwNnZBYCAgEPDxYEHwYFKC9tYXAvZGVmYXVsdC5hc3B4P2xhdD00Ni4wODA0NjcmbG5nPTE0LjUfA2dkZAIPDxYCHwEFkQEuLi5vdGhlciBjYWNoZXMgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P3U9RGF2aWQrJTI2K0FqZGEiPmhpZGRlbjwvYT4gb3IgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P3VsPURhdmlkKyUyNitBamRhIj5mb3VuZDwvYT4gYnkgdGhpcyB1c2VyZAIRD2QWBgIBDxYCHwEFgQIuLi5uZWFyYnkgPGEgaHJlZj0iL3NlZWsvbmVhcmVzdC5hc3B4P3R4PTMyYmM5MzMzLTVlNTItNDk1Ny1iMGY2LTVhMmM4ZmM3YjI1NyZsYXQ9NDYuMDgwNDY3JmxuZz0xNC41MDAwMDAiPmNhY2hlcyBvZiB0aGlzIHR5cGU8L2E+LCA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/dHg9MzJiYzkzMzMtNWU1Mi00OTU3LWIwZjYtNWEyYzhmYzdiMjU3JmxhdD00Ni4wODA0NjcmbG5nPTE0LjUwMDAwMCZmPTEiPnRoYXQgSSBoYXZlbid0IGZvdW5kPC9hPmQCAw8WAh8BBagBLi4uYWxsIG5lYXJieSA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/bGF0PTQ2LjA4MDQ2NyZsbmc9MTQuNTAwMDAwIj5jYWNoZXM8L2E+LCA8YSBocmVmPSIvc2Vlay9uZWFyZXN0LmFzcHg/bGF0PTQ2LjA4MDQ2NyZsbmc9MTQuNTAwMDAwJmY9MSI+dGhhdCBJIGhhdmVuJ3QgZm91bmQ8L2E+ZAIFDxYCHwEFfy4uLmFsbCBuZWFyYnkgPGEgaHJlZj0iaHR0cDovL3d3dy53YXltYXJraW5nLmNvbS9kaXJlY3RvcnkuYXNweD9mPTEmbGF0PTQ2LjA4MDQ2NyZsb249MTQuNTAwMDAwIj53YXltYXJrcyBvbiBXYXltYXJraW5nLmNvbTwvYT5kAhMPFgIfA2hkAhcPZBYCAgEPDxYEHwEFoAc8bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5nZW9jYWNoaW5nLmNvbS9tYXAvZGVmYXVsdC5hc3B4P2xhdD00Ni4wODA0NyZsbmc9MTQuNSIgdGFyZ2V0PSJfYmxhbmsiPkdlb2NhY2hpbmcuY29tIE1hcDwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vbWFwcy5nb29nbGUuY29tL21hcHM/cT1OKzQ2JWMyJWIwKzA0LjgyOCtFKzAxNCVjMiViMCszMC4wMDArKEdDM1hYNUopKyIgdGFyZ2V0PSJfYmxhbmsiPkdvb2dsZSBNYXBzPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly93d3cubWFwcXVlc3QuY29tL21hcHMvbWFwLmFkcD9zZWFyY2h0eXBlPWFkZHJlc3MmZm9ybXR5cGU9bGF0bG9uZyZsYXRsb25ndHlwZT1kZWNpbWFsJmxhdGl0dWRlPTQ2LjA4MDQ3JmxvbmdpdHVkZT0xNC41Jnpvb209MTAiIHRhcmdldD0iX2JsYW5rIj5NYXBRdWVzdDwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vbWFwcy55YWhvby5jb20vI2xhdD00Ni4wODA0NyZsb249MTQuNSZ6b29tPTE2JnE9NDYuMDgwNDcsMTQuNSZjb25mPTEmc3RhcnQ9MSZtdnQ9bSZ0cmY9MCIgdGFyZ2V0PSJfYmxhbmsiPllhaG9vIE1hcHM8L2E+PC9saT48bGk+PGEgaHJlZj0iaHR0cDovL3d3dy5iaW5nLmNvbS9tYXBzL2RlZmF1bHQuYXNweD92PTImbHZsPTE0JnNwPXBvaW50LjQ2LjA4MDQ3XzE0LjVfR0MzWFg1SiIgdGFyZ2V0PSJfYmxhbmsiPkJpbmcgTWFwczwvYT48L2xpPjxsaT48YSBocmVmPSJodHRwOi8vd3d3Lm9wZW5jeWNsZW1hcC5vcmcvP3pvb209MTImbGF0PTQ2LjA4MDQ3Jmxvbj0xNC41IiB0YXJnZXQ9Il9ibGFuayI+T3BlbkN5Y2xlTWFwPC9hPjwvbGk+PGxpPjxhIGhyZWY9Imh0dHA6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvP21sYXQ9NDYuMDgwNDcmbWxvbj0xNC41Jnpvb209MTIiIHRhcmdldD0iX2JsYW5rIj5PcGVuU3RyZWV0TWFwPC9hPjwvbGk+HwNnZGQCGw9kFgYCAQ8WAh8BBRExMTkgTG9nZ2VkIFZpc2l0c2QCBw8PFgIfBgVDfi9zZWVrL2NhY2hlX2xvZ2Jvb2suYXNweD9ndWlkPTUxZTQwZGVjLTYyNzItNGRhZC05MzRiLWUxNzVkYWFhYzI2NWRkAgkPDxYEHwYFPX4vc2Vlay9nYWxsZXJ5LmFzcHg/Z3VpZD01MWU0MGRlYy02MjcyLTRkYWQtOTM0Yi1lMTc1ZGFhYWMyNjUfAQUiVmlldyB0aGUgSW1hZ2UgR2FsbGVyeSBvZiA3IGltYWdlc2RkAl8PFgIfA2gWAgIBDw9kFgIeBXN0eWxlBQx3aWR0aDoxMjBweDtkAmEPZBYEAgMPFgIfAQUHRW5nbGlzaGQCBQ8WAh8HAhQWKGYPZBYCAgEPDxYIHwgFBWVuLVVTHwkFDVNldFRlbXBMb2NhbGUfAQUHRW5nbGlzaB8KaGRkAgEPZBYCAgEPDxYIHwgFBWRlLURFHwkFDVNldFRlbXBMb2NhbGUfAQUHRGV1dHNjaB8KaGRkAgIPZBYCAgEPDxYIHwgFBWZyLUZSHwkFDVNldFRlbXBMb2NhbGUfAQUJRnJhbsOnYWlzHwpoZGQCAw9kFgICAQ8PFggfCAUFcHQtUFQfCQUNU2V0VGVtcExvY2FsZR8BBQpQb3J0dWd1w6pzHwpoZGQCBA9kFgICAQ8PFggfCAUFY3MtQ1ofCQUNU2V0VGVtcExvY2FsZR8BBQnEjGXFoXRpbmEfCmhkZAIFD2QWAgIBDw8WCB8IBQVkYS1ESx8JBQ1TZXRUZW1wTG9jYWxlHwEFBURhbnNrHwpoZGQCBg9kFgICAQ8PFggfCAUFc3YtU0UfCQUNU2V0VGVtcExvY2FsZR8BBQdTdmVuc2thHwpoZGQCBw9kFgICAQ8PFggfCAUFZXMtRVMfCQUNU2V0VGVtcExvY2FsZR8BBQhFc3Bhw7FvbB8KaGRkAggPZBYCAgEPDxYIHwgFBWV0LUVFHwkFDVNldFRlbXBMb2NhbGUfAQUFRWVzdGkfCmhkZAIJD2QWAgIBDw8WCB8IBQVpdC1JVB8JBQ1TZXRUZW1wTG9jYWxlHwEFCEl0YWxpYW5vHwpoZGQCCg9kFgICAQ8PFggfCAUFZWwtR1IfCQUNU2V0VGVtcExvY2FsZR8BBRDOlc67zrvOt869zrnOus6sHwpoZGQCCw9kFgICAQ8PFggfCAUFbHYtTFYfCQUNU2V0VGVtcExvY2FsZR8BBQlMYXR2aWXFoXUfCmhkZAIMD2QWAgIBDw8WCB8IBQVubC1OTB8JBQ1TZXRUZW1wTG9jYWxlHwEFCk5lZGVybGFuZHMfCmhkZAIND2QWAgIBDw8WCB8IBQVjYS1FUx8JBQ1TZXRUZW1wTG9jYWxlHwEFB0NhdGFsw6AfCmhkZAIOD2QWAgIBDw8WCB8IBQVwbC1QTB8JBQ1TZXRUZW1wTG9jYWxlHwEFBlBvbHNraR8KaGRkAg8PZBYCAgEPDxYIHwgFBW5iLU5PHwkFDVNldFRlbXBMb2NhbGUfAQUOTm9yc2ssIEJva23DpWwfCmhkZAIQD2QWAgIBDw8WCB8IBQVrby1LUh8JBQ1TZXRUZW1wTG9jYWxlHwEFCe2VnOq1reyWtB8KaGRkAhEPZBYCAgEPDxYIHwgFBWh1LUhVHwkFDVNldFRlbXBMb2NhbGUfAQUGTWFneWFyHwpoZGQCEg9kFgICAQ8PFggfCAUFcm8tUk8fCQUNU2V0VGVtcExvY2FsZR8BBQhSb23Dom7Egx8KaGRkAhMPZBYCAgEPDxYIHwgFBWphLUpQHwkFDVNldFRlbXBMb2NhbGUfAQUJ5pel5pys6KqeHwpoZGQClQEPFgIfAQUQJmNvcHk7IDIwMDAtMjAxM2QCAw8WAh8BBStTZXJ2ZXI6IFdFQjE3OyBCdWlsZDogV2ViLkhvdEZpeF8yMDEzMDgyMS4xZGS/Gx6rxzdJpCUf5WchaJRbjfwY8Q==" /> -</div> - -<script type="text/javascript"> -//<![CDATA[ -var theForm = document.forms['aspnetForm']; -if (!theForm) { - theForm = document.aspnetForm; -} -function __doPostBack(eventTarget, eventArgument) { - if (!theForm.onsubmit || (theForm.onsubmit() != false)) { - theForm.__EVENTTARGET.value = eventTarget; - theForm.__EVENTARGUMENT.value = eventArgument; - theForm.submit(); - } -} -//]]> -</script> - - -<script src="/WebResource.axd?d=Dh2VENdI9XyWNN0f7DnYfR8WWRCRIzdVqal2y0yjiQ5nC_eHhLchYgnQDHIk0d3RCcSUMVZ36ciRD0qmhXKmeu3S_RE1&t=634981136287450696" type="text/javascript"></script> - - -<script src="/ScriptResource.axd?d=I9_m2Hb1Tv_B0qTMDG8bMbnkNSHUkv5oUaG9-V5NZ8qQ2VFlu60I8y8gfr3vPmZjbiPnu43MOQdFVDeYF-nDAEKBLmyxD3DCTGmes9NNbbvaDEHyEuuRWgccIkK3ik5TI48YGDxjHjqdn-gTK4Fkgd17LGw1&t=ffffffff940d030f" type="text/javascript"></script> -<script src="/ScriptResource.axd?d=8vNbe34dAujgZMPnfnacfjeoweX1vHgyns8KlAV4vpGpsZC9Cf3pro__lv8ekBa0NiCgXGMMolzOUNH__lrnEI_qjlNBIAuuLeemtAXV_i6E0QIMZa8nGSYmWGF5nQOJK3rmZzvTxsr2Mh4Ebdba_1ywGLUSH_U_XIe-jzecfRQwwvjZ0&t=ffffffff940d030f" type="text/javascript"></script> -<script src="/ScriptResource.axd?d=VZKNgu1isPaAINPNmSDkniHRmEiR365Y3EPnMj7AXSlsW-OjQIYc7VPoltqjVULZ1g8K9CNDrBJuNvUVOZhFqH3NS7yTvcU3NnCeS_FcC9dLDDQ8Q9UH7PW6s-B2gF04VAooHH3Ji69sDY7LPmffv0PShiGc1206s_RLAIzuI952BGa9reXAmYClCuFJH4FjsvPZoM7oG82eR9HPyOS28x0KmiQ1" type="text/javascript"></script> -<script src="/ScriptResource.axd?d=H0ET7B4U8EJwmcAbxjSGxSsqhUYAPJWkcrAuejTBaZ7N1SX_jc3D8QuNKUPa0lO4X3QHb4S3pibvaKNYs1ChjXro9ahCfiZGcYIQu6Ypce_q7YOm_PkXbcyD93f6aDlH4D9eFkkuLiE9Ax4WQgrrygMqipqtLqR7mio-gp6w-ttXgLxtrsFRt-pUjltSCvHgWUwBtVr9wTSTuzeTLswFqWhBmRPpN7g52pLMsR4cwsSOiAKUeb6dRJ_DZWWUA7Gz0XyQM93WLdA3NKoaC8qUufQM3ZOa5RAudzueB87VFLfeuhZXxK1-AsHyrJkHMiOGwGZjN55yCPtP1BEwdRcWpCJwU7Y_efv4APmLdYZJuvt4AxhKqZdv9FBT2n8FSDrgUdJXxmOVf_5r2_lt_khWegXBwRoygGjD3nKfQf8Q-zpyIsJZZDzQ8Td_2c9eDB4Zy1LRk5dNsNZy6hAaWo_Uq50DOnrNf0LY0qwB1ZAd9b-kZLlEUQjaCXSSBeCccOLbgDalKaxQ15-fEh-R_Lqgt1720fRQyzlevhgNz5vknnm2hF_vHLKlKAoJWuuSIFEiIgEz-JeplpCgAtzjjo0mJ2Zdl9v_fAQxwE4XgBXmUTaiSmoT6TxPHJPr-3BmMQSZs2qBNbYrFu53gs5JbsKPA0pdzyHLlfP2bYUDBdjB1oCqq5qW0" type="text/javascript"></script> -<script src="../seek/js/cachedetails.js" type="text/javascript"></script> -<script src="../js/latlng.js" type="text/javascript"></script> - <script type="text/javascript"> -//<![CDATA[ -Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00'); -//]]> -</script> - - <div id="Top" class="SkipLinks"> - <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a> - <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a> - </div> - <!--[if lte IE 7]> - <div class="WarningMessage PhaseOut"> - <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p> - </div> - <![endif]--> - - - <div class="PrintOnly"> - <p> - <img src="/images/logo_print_bw.png" alt="Geocaching.com" /> - </p> - <hr /> - </div> - <header id="ctl00_siteHeader"> - <div class="container"> - <h1 class="Logo span-16"> - <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h"> - <img src="/images/tlnMasters/geocaching-logo.png" alt="Geocaching" height="43" width="301" /> - </a> - </h1> - <div class="ProfileWidget span-8 last"> - - <div id="ctl00_divSignedIn"> - <p class="Avatar NoBottomSpacing"> - <a id="ctl00_hlHeaderAvatar" accesskey="p" title="Your Profile" href="../my/"><img title="Your Profile" src="http://img.geocaching.com/user/avatar/e8a97a05-a051-4da9-bc93-6a830b866aff.jpg" alt="" style="border-width:0px;" /></a> - </p> - <p class="SignedInText"> - <strong> - Hello, <a href="/my/default.aspx" title="View Profile for JoSaMaJa" class="SignedInProfileLink">JoSaMaJa</a></strong> (<a id="ctl00_hlSignOut" accesskey="s" title="Sign Out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC3XX5J%26title%3dzarascen-tir%26Submit6%3dGo">Sign Out</a>)<br /> - <span id="ctl00_litPMLevel">Premium Member</span> - - <strong style="display: block"> - 484 Caches Found</strong> - - </p> - </div> - </div> - </div> - </header> - <nav id="Navigation"> - <div class="container"> - <ul class="Menu"> - <li> - <a id="ctl00_hlNavLearn" accesskey="1" title="Learn" href="../guide/">Learn ▼</a> - <ul class="SubMenu"> - <li> - <a id="ctl00_hlSubNavGeocaching101" accesskey="i" title="Geocaching 101" href="../guide/">Geocaching 101</a></li> - <li> - <a id="ctl00_hlSubNavGeocaching2Minutes" title="Geocaching in 2 Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Geocaching in 2 Minutes</a></li> - </ul> - </li> - - <li id="ctl00_liNavProfile"> - <a id="ctl00_hlNavProfile" accesskey="2" title="Your Profile" href="../my/">Your Profile ▼</a> - <ul class="SubMenu"> - <li> - <a id="ctl00_hlSubNavQuickView" accesskey="p" title="Quick View" href="../my/">Quick View</a></li> - <li> - <a id="ctl00_hlSubNavLists" accesskey="q" title="Lists" href="../my/lists.aspx">Lists</a></li> - <li class="ExtraText"> - <a id="ctl00_hlSubNavGeocaches" accesskey="m" title="Geocaches" class="NoRightPadding" href="../my/geocaches.aspx">Geocaches</a> - (<a id="ctl00_hlSubNavGeocachesYours" accesskey="y" title="Your Geocaches" class="NoSidePadding" href="../my/owned.aspx">Yours</a>)</li> - <li class="ExtraText"> - <a id="ctl00_hlSubNavProfileTrackables" title="Trackables" class="NoRightPadding" href="../my/travelbugs.aspx">Trackables</a> - (<a id="ctl00_hlSubNavTrackablesYours" accesskey="8" title="Your Trackables" class="NoSidePadding" href="../track/search.aspx?o=1&uid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">Yours</a>)</li> - <li> - <a id="ctl00_hlSubNavPocketQueries" accesskey="9" title="Pocket Queries" href="../pocket/">Pocket Queries</a></li> - <li> - <a id="ctl00_hlSubNavFieldNotes" accesskey="0" title="Field Notes" href="../my/fieldnotes.aspx">Field Notes</a></li> - <li> - <a id="ctl00_hlSubNavAccount" accesskey="a" title="Account Details" href="../account/">Account Details</a></li> - </ul> - </li> - <li> - <a id="ctl00_hlNavPlay" accesskey="3" title="Play" href="../seek/">Play ▼</a> - <ul class="SubMenu"> - <li> - <a id="ctl00_hlSubNavHide" accesskey="d" title="Hide & Seek a Cache" href="../seek/">Hide & Seek a Cache</a></li> - <li> - <a id="ctl00_hlSubNavLogCache" title="Log a Cache" href="../my/recentlyviewedcaches.aspx">Log a Cache</a></li> - <li> - <a id="ctl00_hlSubNavMap" accesskey="/" title="View Geocache Map" href="../map/">View Geocache Map</a></li> - <li> - <a id="ctl00_hlSubNavTrackables" accesskey="e" title="Find Trackables" href="../track/">Find Trackables</a></li> - <li> - <a id="ctl00_hlSubNavGeoTours" title="GeoTours" href="../adventures/geotours">GeoTours</a> - </li> - <li> - <a id="ctl00_hlSubNavHelpCenter" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li> - </ul> - </li> - <li> - <a id="ctl00_hlNavCommunity" accesskey="6" title="Community" href="../forums/">Community ▼</a> - <ul class="SubMenu"> - - <li> - <a id="ctl00_hlSubNavTellaFriend" accesskey="-" title="Tell a Friend" href="../account/SendReferral.aspx">Tell a Friend</a> - </li> - - <li> - <a id="ctl00_hlSubNavVolunteers" accesskey="+" title="Volunteers" href="../volunteers/">Volunteers</a></li> - <li> - <a id="ctl00_hlSubNavLocal" accesskey="z" title="Local Organizations" href="../organizations/">Local Organizations</a></li> - <li> - <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li> - <li> - <a id="ctl00_hlSubNavBlog" accesskey="b" title="Blog" rel="external" href="http://blog.geocaching.com/">Blog</a></li> - <li> - <a id="ctl00_hlSubNavEvents" accesskey="v" title="Events" href="../calendar/">Events</a></li> - </ul> - </li> - <li> - <a id="ctl00_hlNavShop" accesskey="4" title="Shop" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop ▼</a> - <ul class="SubMenu"> - <li> - <a id="ctl00_hlSubNavShop" accesskey="j" title="Shop Geocaching" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop Geocaching</a></li> - <li> - <a id="ctl00_hlSubNavIntlRetailers" title="International Retailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li> - <li> - <a id="ctl00_hlSubNavGPSReviews" accesskey="w" title="GPS Reviews" href="/reviews/gps">GPS Reviews</a></li> - <li> - <a id="ctl00_hlSubNavGPSGuide" accesskey="k" title="Guide to Buying a GPS Device" href="../about/buying.aspx">Guide to Buying a GPS Device</a></li> - </ul> - </li> - <li> - <a id="ctl00_hlNavPartnering" accesskey="5" title="Partnering" href="../travel/">Partnering ▼</a> - <ul class="SubMenu"> - <li> - <a id="ctl00_hlSubNavTravel" title="Travel and GeoTourism" href="../travel/">Travel and GeoTourism</a></li> - <li> - <a id="ctl00_hlSubNavBrandedPromotions" title="Branded Promotions" href="../brandedpromotions/">Branded Promotions</a></li> - <li> - <a id="ctl00_hlSubNavEducation" title="Geocaching and Education" href="../education/">Geocaching and Education</a></li> - <li> - <a id="ctl00_hlSubNavAdvertisingWithUs" title="Advertising with Us" href="../about/advertising.aspx">Advertising with Us</a></li> - <li> - <a id="ctl00_hlSubNavAPIProgram" title="API Program" href="../live/apidevelopers/">API Program</a></li> - </ul> - </li> - <li> - <a id="ctl00_hlNavVideos" accesskey="7" title="Videos" href="../videos/">Videos</a></li> - <li> - <a id="ctl00_hlNavFollowUs" title="Follow Us" href="http://www.facebook.com/geocaching">Follow Us ▼</a> - <ul class="SubMenu NavSocialMedia"> - <li> - <a id="ctl00_hlSubNavFacebook" title="Facebook" class="SubNavFacebook" href="http://www.facebook.com/geocaching">Facebook</a></li> - <li> - <a id="ctl00_hlSubNavYouTube" title="YouTube" class="SubNavYouTube" href="http://www.youtube.com/user/GoGeocaching">YouTube</a></li> - <li> - <a id="ctl00_hlSubNavInstagram" title="Instagram" class="SubNavInstagram" href="http://instagram.com/gogeocaching">Instagram</a></li> - <li> - <a id="ctl00_hlSubNavTwitter" title="Twitter" class="SubNavTwitter" href="http://twitter.com/GoGeocaching">Twitter</a></li> - </ul> - </li> - </ul> - <div class="LanguageSelector"> - - -<div class="LocaleText"> - - <strong>Choose Your Language:</strong> - -</div> -<div class="LocaleList"> - - <div class="selected-language"> - - <a href="#">English▼</a> - - </div> - <ul class="language-list"> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl04$uxLocaleItem','')">ÄŒeÅ¡tina</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl11$uxLocaleItem','')">LatvieÅ¡u</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, BokmÃ¥l</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li> - - <li><a id="ctl00_uxLocaleListTop_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleListTop$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li> - - </ul> - -</div> -<script type="text/javascript"> - - jQuery(document).ready(function () { - jQuery(".selected-language a").click(function (e) { - e.preventDefault(); - var $loc = jQuery(this).parent().next(); - jQuery($loc).show().position({ - of: $loc.parent(), - my: "left top", - at: "left bottom", - offset: "0 0", - collision: "fit fit" - }); - jQuery(this).addClass("Expanded"); - jQuery(document).click(function () { - jQuery(".language-list").fadeOut("fast"); - jQuery(".selected-language a").removeClass("Expanded"); - }); - return false; - }); - }); -</script> - </div> - </div> - </nav> - <section id="Content"> - - <div class="container"> - <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last"> - <p> - <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span> - </p> - - </div> - <div id="ctl00_divContentMain" class="span-24 last"> - +<script>function utmx_section(){}function utmx(){}(function(){var k='3682814-19',d=document,l=d.location,c=d.cookie; if(l.search.indexOf('utm_expid='+k)>0)return; function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write('<sc'+'ript src=" '+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();</script><script>utmx('url','A/B');</script><meta name="og:type" content="article" property="og:type" /><meta name="fb:app_id" content="251051881589204" property="fb:app_id" /><meta name="og:description" content="Use a smartphone or GPS device to navigate to the provided coordinates. Look for a small hidden container. When you find it, write your name and date in the logbook. If you take something from the container, leave something in exchange. The terrain is 2 and difficulty is 1.5 (out of 5)." property="og:description" /><meta name="og:title" content="ZaraÅ¡Äen Tir" property="og:title" /><meta name="og:image" content="http://www.geocaching.com/images/facebook/wpttypes/2.png" property="og:image" /><meta name="description" content="ZaraÅ¡Äen Tir (GC3XX5J) was created by David & Ajda on 10/01/2012. It's a Small size geocache, with difficulty of 1.5, terrain of 2. It's located in Slovenia.Kadar zbolimo nam pomaga...When we get sick, they are helpful... SLO:tir je danes zapuÅ¡Äen, vÄasih pa so ga uporabljala razliÄna podjetja, da so po njem dostavljali material in odvažali konÄne izdelke." /><link rel="canonical" href="http://www.geocaching.com/seek/cache_details.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265" /><link rel="alternate" href="../datastore/rss_galleryimages.ashx?guid=51e40dec-6272-4dad-934b-e175daaac265" type="application/rss+xml" title="[Gallery Images]" id="GalleryImages" /></head>
+
+<body background="https://lh6.googleusercontent.com/-PoDn9PmtYmg/UGnOZLEQboI/AAAAAAAAAHM/hBXxerWnSdA/s254/lek-verovskova.jpg" class="CacheDetailsPage">
+ <form name="aspnetForm" method="post" action="/geocache/GC3XX5J_zarascen-tir" id="aspnetForm">
+<div>
+<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
+<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
+<input type="hidden" name="__VIEWSTATEFIELDCOUNT" id="__VIEWSTATEFIELDCOUNT" value="2" />
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="EF+BZPhV/l5Um8rFyzxSvVUeWESKAxnBqUN8887IInH6se2ugRYVVFEexgN29b0MyX1EBjfJ1/T7tlxXAfFI19Vbfzh2aUuJpcnJxomIP2xRSZg9QDqXzoCn99Gt9+oz5mob/gKvsxUNt2gkutgKV9rySQWmU6VRtgqkSzW2HLZxRkuAAtYsWv75MrdLMQNyzeTQIjnNudJrrBhHpEB1vCihOdr0JBO7WsrANzPeoG7F/fZRHFHcgywtBWEZg9j2CfC8ww0t2qWRHW9pfXVu11nHisu18mBDFExr9G4UFmiL5TxxNwIABAC987OjgIRMzUz9NqUlD4S98FhKu1duZb8D+AqNhzWXO7REyVt4nQA+u1eVs4WIRmfsOfaSA7x/Ua/GL9vQT/FFEDQSei+Udr8z0LgkPMVH1xuHDBhEOx1IuQE00zaMmDbMzba/qMToeyYm4JuY3BRDG08qO4JjVZj4JSnM0597bg2i9LppcvF210Jceeg2j8282qGMbL/fj4IqXFXmhKQPEdzg835CbkyCtlUORVrnEWghvqAxFSWPH6+9kgDUNt2Ar/FKzIVIdbjZvQehuos+4rGH8C2LoujV7ECRgkHy8f570aMJmtX5s2Co1zrRx/nlp9mYGWJgOAM7mPbqYMfiFNJM6o1lXOdZKWNkJTM3CzEefh0a0ZyWkgFhvwaPyVwnoTWdMxqj5Gh5vB3y5EuW1v7V5TCOcCE2DQmKR658QAqdhSGc4HTMMjAOkUuo0vgFTywnhVtXKXipWq0nEWA1mMUKF5wgEleaV5ayinvGlKuULkbeEhQdhpvT6gbqicyhkdLJS4GG6c7MTrwuHb5FSzkKGrmYCjSf+YWhnFUJvkwcTE6EzJP9Yofr+ercZRkAVaH41sNw85zSF3Et6cp+4dBI+zdDBxoQspWRe78ccVboYHeoAsheTj9Q6JyK7L5TwZSo6/QEbFkxfcjETL2UYTOsDh79WhgXB+sGzAu0nChZyLOpb+N3MHvATYji+6MugJ+fK9C9etBWQCqVrjaYn+5GbsDs7lzFvMbFi6i0OosqUrOAl/lpzPNN3nBJId4Lz0B7wiKAZSTtu6+sdQbeIJlSV3JSZojEV3noUH7m6P07rG5pmyLXV7+kF/QcaGy/VJ8JIrR1V7XcyTnoFij3I3NncTt6u0UPVxzuc+cL47kuPvADnZO5KyllSCQ+iSzB894f+KfG57IoocAxgA58j0oIa1U7Uu8thy4L5tz773sqso8FghXI/UicSE0FLc/CKz998Es8UEpl1Ww+3E6ZZ1oDyQi/WJBAknHEU9+OP6LLURch7dhS5W6RxXyi4R+pZ0Kqbj+A1dtX4KJD13lKqbsnXoZ10HTYf3i4WlnmsiWnDGG9Exu0KBvRHUcmZgjz+2IWfPDNOcbV7pVO1XYHpnzJGHCeQc4Jq5TLAQ7CCibIOJmVEMKgcukvo4LNULDbnZVdrCFhDaCYnKotDL3LHdvfMevJlAzaFGni96tj/wWxAn5C2u1furTspvXySgRY3hZt0FeLNiOEX0UfyTJOt4rcO2+Lfh3jHIiCKz5/HjqK0TdZ+EiTj0jQp2oZmQTC2J4GpNLkeehDteYWKZehaOTLG9ZirjUHD8BGKzA1PRcTw2GR2hkUgOoENjWpkw4x4N1xpFZaBg4mJhTm8kD6MgIIWPjsv9alLjPmsamYCP5LcslZjS3aL9XKKJHmjHKSNoZ/PbJ4XXIwEz+4PD4djG9mpJprsYE0i3EiPtDkrun3u1as1WrUsbn5PIWepH3/xdRwlYKyzy5eOVWqWNueJQiUXwDikUHISaXm9czdu0oGfXj5QeYuElxUOAiF1Ix1+8ZoaN3DKSm0khAY48PtzqVxDPQ5KXzfNaHQirJMWpNjFU7oSUHt6GmPus11QgFFYEyEYLtwslUeEEv93NdIuavXAbq7tVlw62qCPjKH/tHpKLzv6qLi/w6ba2htL4y2TmhY3Sp2KQQzFHFvtVCssexuE03TdlaaDGPcBek9s+rryUL2bNz1ROhrYQ4l+b6XqR2I7wPHURSVlQq7Tk4BnIMbmowehhjqpARFBCVPRKMG58u8dr+VvAhKETXqAKtPc3NdVjtunGHNlMJAH0Jlwlct5Qw7M8cSq2HuZX++PXuac29mc9ObZ1x0eeq33fca0IZijFEChO4I3xLNic9MqL9j8Q7CNSWkP45j7khFOqvaeNCSucVL2sf4DZQ31ZgVEm3qkwVUimLpHUe/R7E66Nx6Ke8/uECC2lSVWCQyI3BY/0wVJGGY5Rrw7k0XnBgWz4S+kLOfvm899z5MMGH6dVjh8XkzlGs7fx08mSTP1bd9F1I6k8CWpyZcRUpZGBP0Ve1ebqCsKjbFhhlM7/TgtD2c6KjiRTawT2u0hIV5fm+uKDrpSswRwUNpS4x/z8aQ2nL1gNajVzpKe19kM0xzCkXD4q2o67AnwPsVK931Yv4ZxC5gts4zSgPY0RXCenvLYZxtop8+/16cEnNv+0jp9tTq1SNYm0xzZL+xxtFrE7gv3NXx7K6LTGeb3hCJxAq7okYI2KzITFoltHyRUjSbvleFW4zEISorNIreViME400/b9GfHZU6PdTEXXO0/x7ZXUqlndMdMdSkP2km6PNFauuzle/J+mqQ8m++QRxoAMuEVjA0VtBvu7b5jndI/aajtNJxmFhIoR7FOFkck41AoH/4RTwl2j3DBvtikUQ8mPtna+pH9TFIOqb4QT9wigV2ADQ58VxKe5LOe/e8Bm6qGZpX0HzHpKaJw4x8N/ABJSGW5dhFTywqsoIJymJYNAT6mHDtpkjVIy3dDi1XS5bcguriNRdnCo9Q+SqGw0O/vfcFl2CXjOH6MWfq8l4HtE2V0/fPZtakn82Wcwh+MOWZ/CNiGWpDLnqPns+jt7GNox46dRn5Ys4rladasSWvCEo2LuqMzUOcqArolqP5mRwgyOj7xB9Gz7hxS7tXDFUkwKkkFWZoGEoym+zH0P6rLtOdXpZTMIqzIW6vlsobonEZM+lNDwPQylXITQdVb/PmSydKu4MTGzZg2gv+sR52yDOjouZRseLHSznSZxqV39w1SzNfFl4ORTgQf75zuKHHZVT4IJg8oguO9WMxj17i7zZ38BKoCQ2Ke4u80dblirBqIJA8qhD97vy7ACKyeTDnTTltw7NVGtMz1Z53ITo6pjIkxoyIno8paYgUCzphXLD85c8qeXXHWBHB833VE2LIlQjn8noQgH6LLnhpKiie/i0Bwa7yuHl46gOWgNWN/p/anfu6xVh7F7KE3Rigb298eZ+egLZyrVXdsJQtV/GXyf2Z3fOeEaNdG+tZOmPTgUBnEc8EmVUENTMGyrCW7bQUalCdK8rNY6yIxVP3U4H37oUPJmLAvzgQCOHW8czjeD0+MAV7H+R6bz947t3G5jfuTytRqHlvDEe0be1dDIynat9n+d1RvuwoxovvKs8c9gSxw2hhu0MdZZrV+Y9vP5pyq5CUdIZm2bRZVnVmn+CwfZzmdkGvaEcnMkB7nMtV7rnkvlc8kY4/5UL8xTTpGlQukR5zvjxlS3GwMOV0Rj4f7kPVj/dUSDvGLC8WYIVbeN9LbmVUd2iuOqHBHiKmU3Q+mX2M74mvxRmwB/1RrmyaKO8D5Bn5EKd1H+GkMc12eMyKT6KKYS3IAfwBma7uAaCnIZ5DWYsCL0sXjPRpb/wVQ+dIehZFlywLcuh/HEYVJq17JvqLeFr5Bdi+kxJS/CBLidFtXe93rfmyvw0TL+LrWb83Ci+qU2DK4o/BQ6jI0amx0GhS+lMXYYv4RjVPwmikjXYzHpkyvrOXi/H7DqAX06g6EADJaF6Zlb9E7l5TADocUMRMm1h/kmupiUgSOerR5d6LDQPZg+c0KzKhIo8/SIuyj1zluftnFncPuIBbP9qADA6ta37B28y5UHDtrXXxd1Ei6GLZD94yFyFx+zhtSRDldBGN3Ds/kBIgR5tMPtlohOJjBu0mrSzT2xQjkDJCNMUu1x4QFk9mJ6RYpUeCojpuPx3ktN8DrzxvBSuQArF6pEBLD2RZpXQZtgffg0f7rt/miuNFmSRZcqmzsdkpjk0WhxI+kojObRdY0cXT8gowye/0xblmwvLEQEAhXHZlfxwTgDq2eYMmfUnpV+vf+dFQBE2Nntg45kDExjNvdzxgheF5Aj33/W87IJ55nYfi93bjfAkPbaichmHeJLe8WMT7nicSEzC+JcVP1dZKzCnvBU4S+7QZjIGNO7jYUI1g49P0QSoVxubsk1q5dwpTk/iIh/3bjkLbM1e9u168yvKTgFA7OAoJB6d0P2AvtzVzIaLt0uIMRVMF+vNSNzcrJbT84JWWDtkzZXFq9HYRWdvhjLjFySc3XU/3QfmIjBLkkHuubp+cGjJCS9i3mRGmfi9Tfng7KR/SYC8oWtIcaL6RiTo/wBv5pkJRARfUBV/y2TBfgOfnpozEvj+ofJL8+yQah/Wkp/TlrARUux1gis1osOWi/CX2irQm9dIzNZ59GC3SU37uwLtjOiNYITXMP+8VAO51f47dyExJAHrxAPOMTPRBIV536Mbo8OKIOdUee74or3tcqEAG32InsHC7oLGv7RKM57O7Z9W2QpV/Q+ZHw/HzIyglu0ljgkrO6sJrq9QGrQyD/m4QHerlmm9DX/G7IAl07eHF6BUq8AAiDAMqWN5dz5vhaYSXZqG7Wjv+n2dqNbE4flRJRDK6bnzKAiocVBz+T1abNwKBClKUMAee4eQXodfXRE4WVD5L/Vv13E41KMutLYQDpmSpddXlCv/FgAblvo19ib2rmIp0BTJWBVRso08RYyV64QRMokqGiJoSxq7kUD0fQzjJzAAWu2u+TqOBkh8iCwyhkb00x38v8gugiar8ItDvaSYqPebRWVCOog3d/5BnEfD7ttQ0tve2jPptTaaOl7cph5jVyvhIH0EVhqul8/Wnb5GlQmQxalmT5gsvOS4kmrQq3bMRwxXb9cvjf3zj93p+h50As4ARjfCM8YDgUUkE1pLzw/P/Ak7F8XlCwkfsWwusyiyxkDDromsMjLmQjyPhVmOFbR1Z5z6aMb28qRCT+au2O3YF0uHVc2LTG3lz4AkTwYDvXCaT7X91Mmg9" />
+<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="lGbHh6bF2Iaw3rJPC11mCJOpvtTeYkxKk11y2nApcvb0wuYbYu2sSdE22GFEmEp4jAsqb4z32zhzahttw31QJJqV6+GyXR2+R7rWDCoHCKt0TwYFxg3wV3YnAc99/P1ZY1Hs6JCLYhB+DrDGPc65qjQ45hxA/KoSbmHHVmR1Klm5+kVweMrQYJAhrXHHCbehtL6uoBKSwKCHvyyYPI8Xf9yoWAzWRGyNOCWmao6MSfbCmaLGkBD2vfA9ng9D8G+ygbZJ2bYN0NxjnubE/OvFJbI7vEs9CI/5RJvIBAdjjQBCU3Yqfdhyz740CdL2pV1vfYmcdlVjntHlv/a0jlNec/TBak7tB3BphU8qE4KwLChWIKsa36UpYC54/jDDm8eju1hiziItkd2owD9r5fmymZj6UjgFcZRM7nH9eCKlke5kan3Cc8eV5+O8ssyGegX0hjJwmuYtxp5dXJjE3gKpxXq0pXdlRNbagJUDDeCcsv8M5WkZAXqS/Jm3YO5SkQL24840vzfSRG9U2blCf5Gjp8YByaAHQPERGI8giQoYDh3Ed+s1DPW1w6fO7r2K17tKTLBBUK3gRUbYsGC/HnGhiQHeqz6/XeHr0Hs/NKgN3s11s97zU+dKChWSHjCSicYC+u3+nPzwWfXddQL0WLCDPio/UaKvEk+bVwfxz0rY5Zk1Fgd7Ti+H0hkYuMk4IEmdMg7AR5VCaG6qAg3lBXQkDL7QIzEZceQdGO+QP1dgGFAsMxdVadEiDEwE91GtPBw/Q143xoPNSWyb0vV7bj7YcsLDc/Swz9Qd0wAcLUusObPK9CojtfG23Ap5Y3F1iabdFJK4ossVK4rm+lqK45iCQd6iWUVn0ccJYQVaW3jxQzCa2LAPoFIweRO08V+S0oImiFFQ9Kqqi82xG1oFLRWEVTIeIKgdZt+QveeidUwpeQEdQqd+l6fc8LrcpdkzQT4ywQ9DcZm9zViVNWztH0Vu4U8FyOXRsh4O6k4aXfvWtBRbKIYFjvijC1wBqZJdLXzk1jqPD84Pzg4pUodgfYVS4kB2QkTN7IU2Q4uXvaU/s4lw4HTlKmA//5p/eHH/Rg9XHO0JeCm/zmMbIJrwEGRVuyY4DtlVf/ALfAonCZ5ZFXpZWZHBXXFmT8OU/JswqnL3mdRxpH7lctqphaIoYfxB/+BVmLZM7Udc2UpBOsvZAfuRvs9x765StviMYcKeRMFaqRJewf6kgemVouceWo/LBSMyyw1hN7mKjkC2U1E9gz1+Kc0G9L6IgI4gd3MsS6yH7BGowdBy8Yry9Aqet7tA8hrVzKXR6HnoVYJukZvkag9mgbRdlr5GVm2QP8jylUg1W6wjZj/JJvVem6Uo/mXr72G9ThY3dsYvywh6cvtZO7yD7szxi163cJF2ZkWNnrwoljwRrNJujybR1UgBkzYTZTgSmBmjwt9vTTJccw19IBoGk2xrkoGthWn0OqBjLl8nlsr9ZnCRZtW7ZXyslZg0IkBbFqBngwRAYCnYpVY/75zS/UXIX4CXTbUlTpxCO0YkKSmdDSWcJ1prqK/N55gAhH/r5wH+t5Vg41SWAak/v95ypXJYqttHDiDD6sRO6+5lOiFqTWLYJbEF88NE0ymhUgttzHibWGoiW21T4UVkJ2Myck0YZ1WPyGEvSwcETfGMBpBmfG5ZfLSKF/pqI1DCsVk5dn5xXCEIaywAOJkrg3a9e2SpI3Ry3qxRa6itJzJpgxZ054G/0oiI0QSJw+hu6UhuZwen0HadcvmNDRLQPuFBhB8lZHxe5yclVuHOOIFf9OOSGFXW3LfWXIfZMChbcJ5d/OCjhBiobcpuxZniEsYlykkG1jZrUf2AmJXYqgB0oDqHfK8/Gib3oJ40m9rx5r8NKpwi5+fUxc6C+jfrkT4+xuCv/YAFXuUZIEBijpk7VgojMSct1kAeuHvoDCFzny+VNBPzzFk7kd11WxtlaOGt+x/9nHPJsBS5wmG1oGi3CZPA5OT8YLHXxqaEoHBUZhYBrgwlv+t+KNT9I3ZsNWzbKXz6IJ+p8g0tR4vbwzjBxtfQwzuwmLTETqJN6n1ufewnl38wVIPyqqPhnTqUmLYF6NpUXLKFX4tUx/kgvJrlZfi7jSR/yhBlnzaZ57yyjncyVJG5/X/MwNOQxoHH7KrZFTcA6MCFzroPQ9x0hAgq4FTaO9KVk3KYx+vB4LU+Cg7bx17GVKBGUuKITbf8fsaYfsnja5+kzB1VE+x/YwNQmE8hmwVC3/VHr/GuBXDu5/Lq6LDxkFYnW1ugNVPsJwI9Eafkdov8sHTvx3nnk3BrBRlbugJAVU5PGV01ysywZpC0o+zXmI9d1WJOCH4/eXvYQLzXjE+HK9EzvwnXjWg+98pcECsZCdMBXYHZteBs+cNE5/OzA3TeSe6QDgu3cARhmeRmoQDg3LIzgA8dZoq+xGfVP8at7SVt4Cq//tgeNet8WMrrv2fRhNMaJ+2H2Idx4Ir1mTOQVUuJdlQd+AHSsm0UAtESHHfO5XmVj0pDRg0dgj1WHtGqRDRMhYJejvp5x9/38GRhj6MsfSug8LwBCDTToc4N/h9fTogY60cpR9NYGd+vvQHcmibJWSTnaPgED99Da5NH9kiGuPD/+dS06rJzObGNLdZjRxqYbF2SThMb4gt5nqliqbHZc9U3f0MCK5EWxGLYnjfQ4eIu076NAzLtyyi5XaJzaMeJDMhJm1iyU54sMMHMQuXTFbkfnurns34aEGgmzqLpWp0t6fI7+7vz4HzyRDKPfJGSep7jwOGCoS8Rg6lYeX0Q+oH/mJMJTH8+c8yKdcw8i3I7p1hFHXYUDIh59sygCe8rcWwBOto8EAlEtHHzMu9WwniG/quV8aoibyeCvVqf3jE7Z6FIwXYlt88KXX1oL2SppCh5pIXjH0aURToNH5RJ56MZF1hrKS9Tsu/W5Ab7hqFPUskFZqvGu31Se5TTxP1Z0SCL2iwbryDb1kO9z0u4+iNOiTshGxLIFChZoJPT30fVLExwba078dD8KVC21dbOYY+Z8Xgj9ONtnd7kpnRniBQa4ROfvMsF4+rgy1g2Uq3Z0fs1Nt5K23l7e7XFLHQqAM6IhFpd1wedW1mJOyDFAzin5Kh6R16M4tkfilkUoLtTsW9prFiCEIAp3PZJ5iT53nVW9KVxAyo3ll2I5bYL/KPpH962shqjRdeh9bpE0GDSQkv2DEsXkWVJdgypd6J+MgKC2N7jKRWq7HDaW1C22AkuAysKWKwNinesrsD2X+UPOP1jEdrZH415qL0NktwyUoUdVMfS2jdno7ycH+WU6vLzU8Y+Md1zGlNjFGePE4u9B9yOwnSeY+P4K8y5UCR7/hSiH//eXY/bkPbWZgWDatcExQVQDmyVlDmLikrig7DpGDjPox+b5jwGjUzlgLPXvg3YVUdOacOYQDumQm4FU5SloczFS4eDFuRLw2eVX7f5t0kWL9IXJHDLXf2NSvi97vL21y8Vk9GfkiecUWIbkqrnAtwckwhkjxBmNYA6EX1SKd3sK81qpQV/pxDGvGPRW/lBjaT6MwIIlfNCEDUsR1QedwqwxfG4KxTd9oWQPMIvZMsO7X8//I+dTxDYjh7lwefWjDAq3zDNAZdKnA9Z0v+a4dQDR6Gdtojnd45c4186VzUiTZz1UJCgY+kdJTOdKP2uc01lq9AxRNRM5ceGJpBYsZB/3ee7Ou0F3NI0Ifp0sLCNybx/KEFBt3CeXgxoZEwmwDTOiano593XgziK9KasJJFUl3j1" />
+</div>
+
+<script type="text/javascript">
+//<![CDATA[
+var theForm = document.forms['aspnetForm'];
+if (!theForm) {
+ theForm = document.aspnetForm;
+}
+function __doPostBack(eventTarget, eventArgument) {
+ if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
+ theForm.__EVENTTARGET.value = eventTarget;
+ theForm.__EVENTARGUMENT.value = eventArgument;
+ theForm.submit();
+ }
+}
+//]]>
+</script>
+
+
+<script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZETFLbdR8wwRMdub1eDU5ILCHE7OhotblLUuaNwx3HQ7rYen0g2&t=635418606520000000" type="text/javascript"></script>
+
+
+<script src="/ScriptResource.axd?d=uHIkleVeDJf4xS50Krz-yEJRbXY2x1dOBEdM7W-QkNpgaumdwaefPzMErSeG_W29-lHX6vl5G7uDafHaYWCx8Z9aLlo8tZwVtV42ISp6LhT6LbxuVUWMo5GyApWAyPOqkSkf1vCyntgT-PmPv-C6FWxsbWo1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=Jw6tUGWnA15YEa3ai3FadDbNvwkajNGIHz7aGm4w_MLRMuZ5hwlk3bfOsTs3E4cZZ4ktnTFE_MzciTx4exD15JXabrPKGazf6xj6fW1A8vXJoc3OCqf4cg_BDlVl8fQEsQiziDh4kHnJRWZEQotwuLoezlg1&t=7e632e9f" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=LsSN37T_JTo8WmXc7IWe9h7QNKB5hH17UtyHRfQt428U3aulvj53CANg-qZVzIBuh0jojGRwyA5u6DVnEet85JW-JpWduEGLE0VE-2wGHR4yu7MNj7XtsTLWd21Jk8RZENZmygJcHOHGMS1oisYKTWQSIQA1" type="text/javascript"></script>
+<script src="/ScriptResource.axd?d=VUtFLQIK94pF36sSxa5M5Q4KyVgkk4aq_Lj3yxNWv9FE_GBcdEQWlyUYzpoPTO27D4G7EbYHTqxoW35XPdin3tebmTxp-wSfJzzK8-nJzs2HapzFx4fuNPR6OjDBQmtyWLMl9s_v9cfV2Mm7C3dG-PYITU2UMwNSjAESeyXFqfw8frZJE2LykLAMOmhcIMdVDEZ3towfhsTqOSZWPCdiMeHylJ16anMqLsL7z0oT5vyUbvIiPYHpYKrAEJIDFxritjPVOv9orjoRf-8NlzG0PwzvCPCUNUOn0q725aaI6lCODxhDBiPw-ciHHQzmbbGdaID-mnjIV9nX6-dgUyOpCAzwZXAoBQPQ6TU3GjtYmetglM7I31meDWRS7sDj-e3m--4pB0SzCNbw9t_ZQ6DjARVQyTvBJksCHM-RcfVHoBtuq9rOTWynsJGmm_Lg2JD7o-KVYJOAuPGcUEcNWxswz-cLWquZQ3_vABHJxAaFz-lnYYwzEyEWn9I2tPIwXjHtZVAB3g0G-dsEEFKNFYXpU1N0r25KNq4NEKXKQg1QI99Bxq6sUV0UkKPNGk0f24VH7_RXyG7L9I3rXDfYaVq1X300crsUh2Cn0-mUkdpiqhtb63KB_jWzXr9HEzeR_socdD-U_PhMKdYigWqerk55eRcMsVPuiRN1yBkFE3GQiZawEqjI0" type="text/javascript"></script>
+<script src="../seek/js/cachedetails.js" type="text/javascript"></script>
+<script src="../js/latlng.js" type="text/javascript"></script>
+<div>
+
+ <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="C05D5804" />
+</div>
+ <script type="text/javascript">
+//<![CDATA[
+Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnetForm', [], [], [], 90, 'ctl00');
+//]]>
+</script>
+
+ <div id="Top" class="SkipLinks">
+ <a id="ctl00_hlSkipLinksNavigation" accesskey="n" title="Skip to Navigation" href="#Navigation">Skip to Navigation</a>
+ <a id="ctl00_hlSkipLinksContent" accesskey="c" title="Skip to Content" href="#Content">Skip to Content</a>
+ </div>
+ <!--[if lte IE 8]>
+ <div class="WarningMessage PhaseOut">
+ <p>Groundspeak is phasing out support for older browsers. Visit the <a href="http://support.groundspeak.com/index.php?pg=kb.page&id=215" title="Browser Support Information">Help Center</a> for more information.</p>
+ </div>
+ <![endif]-->
+
+
+ <div class="PrintOnly">
+ <p>
+ <img src="/images/logo_print_bw.png" alt="Geocaching.com" />
+ </p>
+ <hr />
+ </div>
+ <header id="ctl00_siteHeader">
+ <div class="container">
+ <h1 class="Logo">
+ <a href="../" id="ctl00_HDHomeLink" title="Geocaching" accesskey="h">
+ </a>
+ </h1>
+ <div class="ProfileWidget">
+
+ <div id="ctl00_divSignedIn">
+ <ul class="logged-in-user">
+ <li class="li-user">
+ <a class="SignedInProfileLink" href="/my/default.aspx" title="View Your Profile">
+ <span class="avatar">
+ <img id="ctl00_hlHeaderAvatar" src="https://img.geocaching.com/avatar/642d2771-424e-4ee6-beb6-efecde3406fc.jpg" style="border-width:0px;" />
+ </span>
+ <span class="li-user-info">
+ <span>Bananeweizen</span>
+ <span class="cache-count">743 Finds</span>
+ </span>
+ </a>
+ <button type="button" class="li-user-toggle">
+ <svg width="12px" height="7px" viewBox="0 0 12 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g class="arrow" transform="translate(-1277.000000, -25.000000)" stroke="#FFFFFF" fill="#FFFFFF">
+ <path d="M1280.43401,23.3387013 C1280.20315,23.5702719 1280.20315,23.945803 1280.43401,24.1775793 L1284.82138,28.5825631 L1280.43401,32.9873411 C1280.20315,33.2191175 1280.20315,33.5944429 1280.43401,33.8262192 C1280.54934,33.9420045 1280.70072,34 1280.8519,34 C1281.00307,34 1281.15425,33.9422102 1281.26978,33.8262192 L1286.07462,29.0018993 C1286.30548,28.7701229 1286.30548,28.3947975 1286.07462,28.1630212 L1281.26958,23.3387013 C1281.03872,23.106925 1280.66487,23.106925 1280.43401,23.3387013 Z" id="Dropdown-arrow" sketch:type="MSShapeGroup" transform="translate(1283.254319, 28.582435) scale(1, -1) rotate(-90.000000) translate(-1283.254319, -28.582435) "></path>
+ </g>
+ </g>
+ </svg>
+ </button>
+ <ul>
+ <li class="li-settings">
+ <a title="Edit Account Settings" class="icon-settings" href="/account/settings">Settings</a>
+ </li>
+ <li class="li-signout">
+ <a id="ctl00_hlSignOut" accesskey="s" class="sign-out" href="https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fseek%2fcache_details.aspx%3fwp%3dGC3XX5J%26title%3dzarascen-tir">Sign Out</a>
+ </li>
+ </ul>
+ </li>
+ <li class="li-messagecenterheaderwidget li-messages" id="messagecenterheaderwidget">
+ <a class="message-center-icon" href="/account/messagecenter">
+ <span class="msg-center-link-text">Messages</span>
+ </a>
+ </li>
+ <li class="li-upgrade">
+
+
+ </li>
+ </ul>
+ </div>
+ </div>
+
+ </div>
+ </header>
+ <nav id="Navigation">
+ <div class="container">
+ <a href="../" id="ctl00_A1" class="Logo" title="Geocaching" accesskey="h">
+ <img src="/images/tlnMasters/logo-geocaching@2x.png" alt="Geocaching" width="195" />
+ </a>
+ <ul class="Menu">
+ <li>
+ <a id="ctl00_hlNavLearn" accesskey="1" class="Dropdown" href="../guide/">Learn</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavGeocaching101" accesskey="i" href="../guide/">Geocaching 101</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeocaching2Minutes" href="../videos/default.aspx#cat=PL939C3CBDC2F2F385&vid=1YTqitVK-Ts">Videos</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavPlay" accesskey="2" class="Dropdown" href="../play/search/">Play</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavFind" accesskey="d" href="../play/search/">Find a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavHide" accesskey="d" href="../play/hide/">Hide a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavMap" accesskey="/" href="../map/">View Geocache Map</a></li>
+ <li id="ctl00_liSubNavLogCache">
+ <a id="ctl00_hlSubNavLogCache" href="../my/recentlyviewedcaches.aspx">Log a Geocache</a></li>
+ <li>
+ <a id="ctl00_hlSubNavTrackables" accesskey="e" href="../track/">Find Trackables</a></li>
+ <li>
+ <a id="ctl00_hlSubNavGeoTours" href="../play/geotours">GeoTours</a>
+ </li>
+ <li id="ctl00_liSubNavPocketQueries">
+ <a id="ctl00_hlSubNavPocketQueries" accesskey="9" href="../pocket/">Pocket Queries</a></li>
+ <li id="ctl00_liSubNavFieldNotes">
+ <a id="ctl00_hlSubNavFieldNotes" accesskey="0" href="../my/fieldnotes.aspx">Field Notes</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavCommunity" accesskey="3" class="Dropdown" href="../forums/">Community</a>
+ <ul class="SubMenu">
+
+ <li>
+ <a id="ctl00_hlSubNavTellaFriend" accesskey="-" href="../account/referafriend">Refer a Friend</a>
+ </li>
+
+ <li>
+ <a id="ctl00_hlSubNavVolunteers" accesskey="+" href="../volunteers/">Volunteers</a></li>
+ <li>
+ <a id="ctl00_hlSubNavDiscussionForums" accesskey="f" href="../forums/">Discussion Forums</a></li>
+ <li>
+ <a id="ctl00_hlSubNavBlog" accesskey="b" rel="external" href="http://blog.geocaching.com/">Blog</a></li>
+ <li>
+ <a id="ctl00_hlSubNavEvents" accesskey="v" href="../calendar/">Events</a></li>
+ </ul>
+ </li>
+ <li>
+ <a id="ctl00_hlNavShop" accesskey="4" class="Dropdown" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">Shop</a>
+ <ul class="SubMenu">
+ <li>
+ <a id="ctl00_hlSubNavShop" accesskey="j" rel="external" href="http://shop.geocaching.com/?utm_source=Geocaching&utm_medium=Links&utm_content=Header&utm_campaign=Geocaching+Links">USA Shop</a></li>
+ <li>
+ <a id="ctl00_hlSubNavIntlRetailers" rel="external" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></li>
+ <li>
+ <a id="ctl00_hlBecomePremium" href="https://payments.geocaching.com/?upgrade=true">Become a Premium Member</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </nav>
+ <section id="Content">
+
+ <div class="container">
+ <div id="ctl00_divBreadcrumbs" class="BreadcrumbWidget span-24 last">
+ <!--<p>
+ <span id="ctl00_Breadcrumbs"><span><a title="Geocaching - The Official Global GPS Cache Hunt Site" href="/">Geocaching</a></span><span> > </span><span><a title="Hide and Seek A Geocache" href="/seek/default.aspx">Hide and Seek A Geocache</a></span><span> > </span><span>Geocache Details</span></span>
+ </p>-->
+
+ </div>
+ <div id="ctl00_divContentMain" class="span-24 last">
+ - <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget"> + <div id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoLinkPanel" class="CoordInfoLinkWidget">
<p> <a href="#" class="CoordInfoLink"> <span id="ctl00_ContentBody_CoordInfoLinkControl1_uxCoordInfoCode" class="CoordInfoCode">GC3XX5J</span> <span class="arrow">▼</span> </a> </p> - +
</div> <div id="dlgClipboard"> <input type="text" class="TextFormat" /> @@ -407,11 +322,12 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet </script> + <div class="span-17"> <div class="span-17 last BottomSpacing" id="cacheDetails"> <p class="cacheImage"> - <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/2.gif" alt="Traditional Cache" title="Traditional Cache" /></a> + <a href="/about/cache_types.aspx" target="_blank" title="About Cache Types"><img src="/images/WptTypes/2.gif" alt="Traditional Geocache" title="Traditional Geocache" /></a> </p> <h2 class="NoBottomSpacing"> @@ -494,7 +410,7 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet </p> - + <p class="OldWarning NoBottomSpacing"><strong>Cache Issues:</strong></p><ul class="OldWarning"><li>This cache has been archived, but is available for viewing for archival purposes.</li></ul> <div id="ctl00_ContentBody_CacheInformationTable" class="CacheInformationTable"> <div class="LocationData FloatContainer"> @@ -513,7 +429,7 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet </div> <div class="span-7 last AlignRight"> <span id="ctl00_ContentBody_Location">In Slovenia</span><br /> - <span id="lblDistFromHome"><img src="/images/icons/compass/SE.gif" alt="SE" style="vertical-align:text-bottom" /> SE 765.5 km from your home location</span> + <span id="lblDistFromHome"><img src="/images/icons/compass/SE.gif" alt="SE" style="vertical-align:text-bottom" /> SE 504.9 km from your home location</span> </div> </div> <div class="DownloadLinks"> @@ -525,7 +441,7 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet <a id="ctl00_ContentBody_lnkPrintFriendly" href="../seek/cdpf.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265" target="_blank">No Logs</a> <a id="ctl00_ContentBody_lnkPrintFriendly5Logs" href="../seek/cdpf.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265&lc=5" target="_blank">5 Logs</a> <a id="ctl00_ContentBody_lnkPrintFriendly10Logs" href="../seek/cdpf.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265&lc=10" target="_blank">10 Logs</a> - <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=52.21625,9.714483 (Home Location)&daddr=46.080467,14.5(Zara%c5%a1%c4%8den+Tir)" target="_blank">Driving Directions</a> + <a id="ctl00_ContentBody_lnkPrintDirectionsSimple" class="DrivingDirections" href="http://maps.google.com/maps?f=d&hl=en&saddr=48.861002,9.186577 (Home Location)&daddr=46.080467,14.5(Zara%c5%a1%c4%8den+Tir)" target="_blank">Driving Directions</a> </dd> </dl> <dl id="ctl00_ContentBody_uxPrintPDFSection" style="display: none;"> @@ -566,17 +482,16 @@ Sys.WebForms.PageRequestManager._initialize('ctl00$uxMainScriptManager', 'aspnet Personal Cache Note </strong> <img src="/images/icons/16/help.png" id="pcn_help" class="CacheNoteHelpImg" /> - <span id="cache_note"> - - </span> + + <span id="cache_note"></span> </div> <h3 class="CacheDescriptionHeader">Geocache Description:</h3> <div class="UserSuppliedContent"> - <span id="ctl00_ContentBody_ShortDescription">Kadar zbolimo nam pomaga...<br /> -<br /> -When we get sick, they are helpful... + <span id="ctl00_ContentBody_ShortDescription">Kadar zbolimo nam pomaga...<br />
+<br />
+When we get sick, they are helpful...
</span> </div> @@ -584,12 +499,12 @@ When we get sick, they are helpful... <br /> <div class="UserSuppliedContent"> - <span id="ctl00_ContentBody_LongDescription">SLO:<br /> -tir je danes zapuÅ¡Äen, vÄasih pa so ga uporabljala razliÄna podjetja, da so po njem dostavljali material in odvažali konÄne izdelke.<br /> - <br /> -ENG:<br /> -rail is abandoned today, but once it was used by different companies, so they could have their materials delivered and products driven to final destinations .<br /> - <br /> + <span id="ctl00_ContentBody_LongDescription">SLO:<br />
+tir je danes zapuÅ¡Äen, vÄasih pa so ga uporabljala razliÄna podjetja, da so po njem dostavljali material in odvažali konÄne izdelke.<br />
+Â <br />
+ENG:<br />
+rail is abandoned today, but once it was used by different companies, so they could have their materials delivered and products driven to final destinations .<br />
+Â <br />
PRINESI SVOJE PISALO / BRING YOUR OWN PEN<br /></span> </div> @@ -618,12 +533,13 @@ PRINESI SVOJE PISALO / BRING YOUR OWN PEN<br /></span> <a href="/seek/log.aspx?ID=3220672&lcn=1" id="ctl00_ContentBody_GeoNav_logButton" class="Button LogVisit">Log your visit</a> <ul> - <li><a href="/seek/gallery.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265">View Gallery</a> (7)</li> - <li><a href="/my/watchlist.aspx?w=3220672">Watch</a> (0)</li> + <li><a href="/seek/gallery.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265">View Gallery</a> (9)</li> + <li><a href="/my/watchlist.aspx?w=3220672">Watch</a> (1)</li> <li><a href="/bookmarks/mark.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265&WptTypeID=2">Bookmark</a></li> <li><a href="/bookmarks/ignore.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265&WptTypeID=2">Ignore</a></li> </ul> + </div> @@ -640,30 +556,30 @@ PRINESI SVOJE PISALO / BRING YOUR OWN PEN<br /></span> Attributes </h3> <div class="WidgetBody"> - <img src="/images/attributes/stroller-no.gif" alt="not stroller accessible" title="not stroller accessible" width="30" height="30" /> <img src="/images/attributes/kids-no.gif" alt="no kids" title="no kids" width="30" height="30" /> <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/night-yes.gif" alt="recommended at night" title="recommended at night" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/stealth-yes.gif" alt="stealth required" title="stealth required" width="30" height="30" /> <img src="/images/attributes/public-yes.gif" alt="public transit available" title="public transit available" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/hike_short-yes.gif" alt="hike shorter than 1km" title="hike shorter than 1km" width="30" height="30" /> <img src="/images/attributes/parkngrab-yes.gif" alt="park and grab" title="park and grab" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p> + <img src="/images/attributes/kids-no.gif" alt="no kids" title="no kids" width="30" height="30" /> <img src="/images/attributes/stroller-no.gif" alt="not stroller accessible" title="not stroller accessible" width="30" height="30" /> <img src="/images/attributes/stealth-yes.gif" alt="stealth required" title="stealth required" width="30" height="30" /> <img src="/images/attributes/bicycles-yes.gif" alt="bikes allowed" title="bikes allowed" width="30" height="30" /> <img src="/images/attributes/night-yes.gif" alt="recommended at night" title="recommended at night" width="30" height="30" /> <img src="/images/attributes/available-yes.gif" alt="available 24-7" title="available 24-7" width="30" height="30" /> <img src="/images/attributes/hike_short-yes.gif" alt="hike shorter than 1km" title="hike shorter than 1km" width="30" height="30" /> <img src="/images/attributes/public-yes.gif" alt="public transit available" title="public transit available" width="30" height="30" /> <img src="/images/attributes/parking-yes.gif" alt="parking available" title="parking available" width="30" height="30" /> <img src="/images/attributes/onehour-yes.gif" alt="takes less than 1 hour" title="takes less than 1 hour" width="30" height="30" /> <img src="/images/attributes/parkngrab-yes.gif" alt="park and grab" title="park and grab" width="30" height="30" /> <img src="/images/attributes/dogs-yes.gif" alt="dogs allowed" title="dogs allowed" width="30" height="30" /> <p class="NoBottomSpacing"><small><a href="/about/icons.aspx" title="What are Attributes?">What are Attributes?</a></small></p> </div> </div> - <div id="ctl00_ContentBody_uxBanManWidget" class="InlinePageAds"> + <div id="ctl00_ContentBody_uxBanManWidget" class="InlinePageAds">
- <script type='text/javascript'> -googletag.cmd.push(function() {{ -googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_1cd2f642-a5e3-42dc-a38f-7033ff6b8c42').addService(googletag.pubads()); -googletag.pubads().enableSingleRequest(); -googletag.enableServices(); -}}); -</script> -<div id='div_1cd2f642-a5e3-42dc-a38f-7033ff6b8c42'> -<script type='text/javascript'> -googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7033ff6b8c42'); }); -</script> -</div> + <script type='text/javascript'>
+googletag.cmd.push(function() {{
+googletag.defineSlot('/1011121/cache_details_pg_120x240', [120, 240], 'div_0bbdd8d1-27bf-4373-8f85-97a5654201a0').addService(googletag.pubads());
+googletag.pubads().enableSingleRequest();
+googletag.enableServices();
+}});
+</script>
+<div id='div_0bbdd8d1-27bf-4373-8f85-97a5654201a0'>
+<script type='text/javascript'>
+googletag.cmd.push(function() { googletag.display('div_0bbdd8d1-27bf-4373-8f85-97a5654201a0'); });
+</script>
+</div>
<p> - <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small> </p> + <small><a href="../about/advertising.aspx" id="ctl00_ContentBody_advertisingWithUs" title="Advertising with Us">Advertising with Us</a></small> </p>
</div><div class="GoogleAds AlignCenter BottomSpacing"> </div> @@ -681,10 +597,10 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 <div class="WidgetBody"> - <div id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItems"> + <div id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItems">
<p class="NoBottomSpacing"><span id="ctl00_ContentBody_uxTravelBugList_uxNoTrackableItemsLabel">There are no Trackables in this cache.</span></p> - +
</div> <div class="TopSpacing"> @@ -699,32 +615,28 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 </div> - <div class="CacheDetailNavigationWidget"> - - <h3 class="WidgetHeader">My Bookmark Lists</h3> + <h3 class="WidgetHeader"> + Bookmark Lists + </h3> <div class="WidgetBody"> - <ul class="BookmarkList"> <li class=''> - <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=14551708-0c3c-4f95-9342-1bb3119e6efe">cgeo mocks</a><br /> by <a href="http://www.geocaching.com/profile/?guid=4d416461-d1a7-4cc5-8ee7-336bb910feb8">JoSaMaJa</a> + <a href="http://www.geocaching.com/bookmarks/view.aspx?guid=8d803709-853c-4f06-974a-861fadf83e16">FTF LIST</a><br />by <a href="http://www.geocaching.com/profile/?guid=76f3cd2a-8ff4-45a8-afd1-4ce98d8474bd">bojank</a> </li> </ul> <p class="NoBottomSpacing"> - + <a href="/bookmarks/default.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265&WptTypeID=2" title="View all bookmark lists...">View all bookmark lists...</a> </p> - </div> - - </div> - + </div> @@ -736,7 +648,7 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 <p> - <div id="uxlrgMap" class="FloatRight TopSpacing"> + <div id="uxlrgMap" class="FloatRight TopSpacing">
<div class="PageBreakBefore"> @@ -760,7 +672,7 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 </a> </div> </div> - +
</div> <p class="NoPrint"> @@ -801,16 +713,16 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 <div class="InformationWidget Clear"> <h3> - 119 Logged Visits + 175 Logged Visits </h3> <div class="EncryptDecrypt"> <a href="#" class="decrypt-link"> Decrypt </a> </div> - <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 112 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 1 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 1 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 2 <img src="/images/logtypes/25.png" alt="Retract Listing" title="Retract Listing" /> 1 <img src="/images/logtypes/45.png" alt="Needs Maintenance" title="Needs Maintenance" /> 1 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 1 </p></span> + <span id="ctl00_ContentBody_lblFindCounts"><p class="LogTotals"><img src="/images/logtypes/2.png" alt="Found it" title="Found it" /> 155 <img src="/images/logtypes/3.png" alt="Didn't find it" title="Didn't find it" /> 8 <img src="/images/logtypes/4.png" alt="Write note" title="Write note" /> 2 <img src="/images/logtypes/5.png" alt="Archive" title="Archive" /> 1 <img src="/images/logtypes/7.png" alt="Needs Archived" title="Needs Archived" /> 1 <img src="/images/logtypes/22.png" alt="Temporarily Disable Listing" title="Temporarily Disable Listing" /> 1 <img src="/images/logtypes/24.png" alt="Publish Listing" title="Publish Listing" /> 2 <img src="/images/logtypes/25.png" alt="Retract Listing" title="Retract Listing" /> 1 <img src="/images/logtypes/45.png" alt="Needs Maintenance" title="Needs Maintenance" /> 2 <img src="/images/logtypes/46.png" alt="Owner Maintenance" title="Owner Maintenance" /> 2 </p></span> <p class="HalfLeft"> - <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265">View Logbook</a> | <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265">View the Image Gallery of 7 images</a> + <a id="ctl00_ContentBody_uxLogbookLink" href="../seek/cache_logbook.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265">View Logbook</a> | <a id="ctl00_ContentBody_uxGalleryImagesLink" DisplayFormatPlural="View the Image Gallery of {0:#,###} images" DisplayFormatSingular="View the Image Gallery" href="../seek/gallery.aspx?guid=51e40dec-6272-4dad-934b-e175daaac265">View the Image Gallery of 9 images</a> </p> <p class="NoBottomSpacing AlignRight"> <span class="Warning">**Warning!</span> <a href="/about/glossary.aspx#spoiler" title="Spoilers">Spoilers</a> may be included in the descriptions or links. @@ -839,7 +751,7 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 </div> <p> <small> - Current Time: <time datetime="2013-08-21T21:12:17Z">08/21/2013 21:12:17 Pacific Daylight Time (04:12 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2013-08-18T20:01:06Z">2013-08-18T20:01:06Z</time> on 08/18/2013 13:01:06 Pacific Daylight Time (20:01 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum + Current Time: <time datetime="2015-03-31T10:41:17Z">03/31/2015 10:41:17 Pacific Daylight Time (17:41 GMT)</time><br/>Last Updated: <time class="timeago" datetime="2015-01-13T10:06:47Z">2015-01-13T10:06:47Z</time> on 01/13/2015 02:06:47 (UTC-08:00) Pacific Time (US & Canada) (10:06 GMT) <br/>Rendered From:Unknown<br />Coordinates are in the WGS84 datum </small> </p> <div id="topScroll" class="TopScroll" style="display: none;"> @@ -944,7 +856,7 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 <dl class="ccu-parseverify" style="display: none;"> <dt>Change To:</dt> <dd> - <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span> + <span class="ccu-parseverify-coords">N 32°38.880′, W 097°23.755′</span> </dd> <dt> </dt> <dd> @@ -954,72 +866,99 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 </dl> </div> </script> - - </div> - - </div> - </section> - <footer> - <div class="container"> - <div class="span-24 last FooterTop"> +
+ </div>
+
+ </div>
+ </section>
+ <footer>
+
+ <section class="links wrap">
+ <dl>
+ <dt>Partner With Us</dt>
+ <dd><a id="ctl00_hlFooterJobs" href="http://www.groundspeak.com/jobs.aspx">Jobs</a></dd>
+ <dd><a id="ctl00_lnkTravelAndGeotourism" href="/travel/">GeoTours & Travel</a></dd>
+ <dd><a id="ctl00_lnkBrandedPromotions" href="/brandedpromotions/">Branded Promotions</a></dd>
+ </dl>
+
+ <dl>
+ <dt>Legal</dt>
+ <dd><a id="ctl00_hlFooterLogo" accesskey="l" href="../about/logousage.aspx">Logo Usage Guidelines</a></dd>
+ <dd><a id="ctl00_hlFooterParksPoliceLink" href="../parksandpolice/">Parks & Police</a></dd>
+ </dl>
+
+ <dl>
+ <dt>Shop Geocaching</dt>
+ <dd><a id="ctl00_lnkUSAShop" href="http://shop.geocaching.com/">USA Shop</a></dd>
+ <dd><a id="ctl00_lnkInternationalShop" href="http://shop.geocaching.com/default/international-retailers/">International Retailers</a></dd>
+ </dl>
+ <dl>
+ <dt>Contact Us</dt>
+ <dd><a id="ctl00_lnkHelpCenterLink" rel="external" href="http://support.groundspeak.com/index.php?pg=request">Help Center</a></dd>
+ <dd><a id="ctl00_lnkMedia" rel="document" href="../press/faq.aspx">Media Inquiries</a></dd>
+ </dl>
-<div class="LocaleText"> - - <strong>Choose Your Language:</strong> - -</div> -<div class="LocaleList"> - - <div class="selected-language"> - - <a href="#">English▼</a> - +<div class="language-dropdown"> + <div class="LocaleText"> + Choose Language </div> - <ul class="language-list"> + <div class="LocaleList"> - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Deutsch</a></li> + <div class="selected-language"> - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">Français</a></li> + <a href="#">English</a> - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Português</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">ÄŒeÅ¡tina</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Dansk</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Svenska</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Eesti</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">Ελληνικά</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">LatvieÅ¡u</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">Nederlands</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Català </a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Polski</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, BokmÃ¥l</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">í•œêµì–´</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Magyar</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li> - - <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">日本語</a></li> + </div> + <ul class="language-list"> - </ul> - + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl00_uxLocaleItem" class="selected" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem','')">English</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl01_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl01$uxLocaleItem','')">Català </a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl02_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl02$uxLocaleItem','')">ÄŒeÅ¡tina</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl03_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl03$uxLocaleItem','')">Dansk</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl04_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl04$uxLocaleItem','')">Deutsch</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl05_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl05$uxLocaleItem','')">Ελληνικά</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl06_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl06$uxLocaleItem','')">Eesti</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl07_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl07$uxLocaleItem','')">Español</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl08_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl08$uxLocaleItem','')">Français</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl09_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl09$uxLocaleItem','')">Italiano</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl10_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl10$uxLocaleItem','')">日本語</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl11_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl11$uxLocaleItem','')">í•œêµì–´</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl12_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl12$uxLocaleItem','')">LatvieÅ¡u</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl13_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl13$uxLocaleItem','')">Magyar</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl14_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl14$uxLocaleItem','')">Nederlands</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl15_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl15$uxLocaleItem','')">Norsk, BokmÃ¥l</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl16_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl16$uxLocaleItem','')">Polski</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl17_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl17$uxLocaleItem','')">Português</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl18_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl18$uxLocaleItem','')">Română</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl19_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl19$uxLocaleItem','')">РуÑÑкий</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl20_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl20$uxLocaleItem','')">Suomi</a></li> + + <li><a id="ctl00_uxLocaleList_uxLocaleList_ctl21_uxLocaleItem" href="javascript:__doPostBack('ctl00$uxLocaleList$uxLocaleList$ctl21$uxLocaleItem','')">Svenska</a></li> + + </ul> + + </div> </div> <script type="text/javascript"> @@ -1029,9 +968,8 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 var $loc = jQuery(this).parent().next(); jQuery($loc).show().position({ of: $loc.parent(), - my: "left top", - at: "left bottom", - offset: "0 0", + my: "left bottom", + at: "left top-10", collision: "fit fit" }); jQuery(this).addClass("Expanded"); @@ -1042,188 +980,157 @@ googletag.cmd.push(function() { googletag.display('div_1cd2f642-a5e3-42dc-a38f-7 return false; }); }); -</script> - </div> - </div> - <div class="container column-container"> - <div class="column"> - <p class="FooterLinksHeader"> - <strong> - About</strong> - </p> - <ul class="FooterLinks"> - <li> - <a id="ctl00_hlFooterGlossary" title="Glossary of Terms" href="../about/glossary.aspx">Glossary of Terms</a></li> - <li> - <a id="ctl00_hlFooterBrochures" title="Brochures" href="../tools/#Guide">Brochures</a></li> - <li> - <a id="ctl00_hlFooterAbout" title="About Groundspeak" href="../about/groundspeak.aspx">About Groundspeak</a></li> - <li> - <a id="ctl00_hlFooterHistory" title="History" href="../about/history.aspx">History</a></li> - </ul> - </div> - <div class="column"> - <p class="FooterLinksHeader"> - <strong> - Press</strong> - </p> - <ul class="FooterLinks"> - <li> - <a id="ctl00_hlFooterNews" title="News Articles" href="../press/">News Articles</a></li> - <li> - <a id="ctl00_hlFooterMediaFAQs" title="Media FAQs" rel="document" href="../articles/Brochures/footer/FAQ_Media.pdf">Media FAQs</a></li> - <li> - <a id="ctl00_hlFooterMediaInquiries" title="Media Inquiries" rel="external" href="http://support.groundspeak.com/index.php?pg=request&xCategory=11">Media Inquiries</a></li> - <li> - <a id="ctl00_hlFooterLogo" accesskey="l" title="Logo Usage Guidelines" href="../about/logousage.aspx">Logo Usage Guidelines</a></li> - </ul> - </div> - <div class="column"> - <p class="FooterLinksHeader"> - <strong> - Questions & Suggestions</strong> - </p> - <ul class="FooterLinks"> - <li> - <a id="ctl00_hlFooterHelpCenterLink" title="Help Center" rel="external" href="http://support.groundspeak.com/index.php">Help Center</a></li> - <li> - <a id="ctl00_hlFooterDiscussionForums" accesskey="f" title="Discussion Forums" href="../forums/">Discussion Forums</a></li> - <li> - <a id="ctl00_hlFooterParksPoliceLink" title="Land Management and Law Enforcement" href="../parksandpolice/">Land Management and Law Enforcement</a></li> - <li> - <a id="ctl00_hlFooterContactUs" title="Contact Us" href="../contact/">Contact Us</a></li> - </ul> - </div> - <div class="column"> - <p class="FooterLinksHeader"> - <strong> - Resources</strong> - </p> - <ul class="FooterLinks"> - <li> - <a id="ctl00_hlFooterTools" accesskey="o" title="Tools and Downloads" href="../tools/">Tools and Downloads</a></li> - <li> - <a id="ctl00_hlFooterAPIProgram" title="API Program" href="../live/">API Program</a></li> - <li> - <a id="ctl00_hlFooterBenchmarks" title="Find a Benchmark" href="../mark/">Find a Benchmark</a></li> - </ul> - </div> - <div class="column"> - <p class="FooterLinksHeader"> - <strong> - Follow Us</strong> - </p> - <ul class="FooterLinks FollowUsLinks"> - <li> - <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a></li> - <li> - <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a></li> - <li> - <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/gogeocaching/"></a></li> - <li> - <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a></li> - </ul> - </div> - </div> - <div class="FooterBottom"> - <div class="container"> - <p> - Copyright - © 2000-2013 - <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a> - All Rights Reserved. - <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a> - | - <a id="ctl00_hlFooterPrivacy" accesskey="x" title="Privacy Policy" href="../about/privacypolicy.aspx">Privacy Policy</a> - </p> - - </div> - </div> - </footer> - <div class="SkipLinks"> - <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a> - </div> - - -<script type="text/javascript"> -//<![CDATA[ -$(function() { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'Premium', null, true]); });var isLoggedIn = true; -var userDefinedCoords = {"status":"fail","data":{"isUserDefined":false,"oldLatLngDisplay":"N 46° 04.828' E 014° 30.000'"}}; -mapLatLng = {"lat":46.08047,"lng":14.5,"type":2,"name":"ZaraÅ¡Äen Tir"}; -var ccConversions = [{"t":"Decimal","k":"DD","d":"WGS84","v":"46.080467, 014.500000"},{"t":"DDD MM SS.SSS","k":"DMS","d":"WGS84","v":"N 46° 04' 49.681\" E 014° 30' 00.000\""},{"t":"UTM","k":"UTM","d":"WGS84","v":"33T E 461340 N 5103109"}]; -var dh=false;userInfo = {ID: 4793174}; -userToken = '4OB3GFHLRR3CGMZFUAPD6CWPE24ZHP6Q7KCBEDNYY5CUNWNQIA32GZPVPFMH6IGAEYKVNNSFLMQ7BBGFDKQBT3BZGZBYKVQ4H5BWKD6MVBKYBTM627XPOUSUP6U4JF7NKKEOYJ4A6LEG2T5B6MG5AMMFOS27KNE4U2BAU4PZHXTIASIYWFYVKCUOKL22KFA6QAHSYC5LPKUTADH2JZH6BXMTYDNGMZXDBT3OPXUHQASIIU4WRAEA'; -includeAvatars = true; -var lat=46.080467, lng=14.5, guid='51e40dec-6272-4dad-934b-e175daaac265'; -initalLogs = {"status":"success", "data": [{"LogID":340527924,"CacheID":3220672,"LogGuid":"f45d0816-d024-46c2-9908-94a492c725fe","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Found it:)","Created":"2013-08-16","Visited":"2013-08-16","UserName":"K I N","MembershipLevel":1,"AccountID":7771619,"AccountGuid":"4c169228-9960-4775-a6b4-bdcd352f98db","Email":"","AvatarImage":"","GeocacheFindCount":18,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":341444389,"CacheID":3220672,"LogGuid":"8ad83648-c096-422a-a4d5-93c1762c7a80","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"TFTC!","Created":"2013-08-18","Visited":"2013-08-15","UserName":"yaochacha","MembershipLevel":1,"AccountID":7859000,"AccountGuid":"30794f4b-c91a-455e-8f1a-1fa1afd0a912","Email":"","AvatarImage":"","GeocacheFindCount":9,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":341054839,"CacheID":3220672,"LogGuid":"dd2aa3b3-0364-4c67-908d-5eb882424b9e","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"TFTC!","Created":"2013-08-17","Visited":"2013-08-15","UserName":"Remih87","MembershipLevel":1,"AccountID":4638242,"AccountGuid":"868ac153-1a8f-44b9-bcad-b225a0567032","Email":"","AvatarImage":"5eca0e89-b8b4-4d50-aacc-84e7cfad79a2.jpg","GeocacheFindCount":136,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":340199614,"CacheID":3220672,"LogGuid":"f9da4abb-b21b-4f68-bafd-7599efd9821a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":":)<br />#111","Created":"2013-08-15","Visited":"2013-08-15","UserName":"Hobbit (SLO)","MembershipLevel":1,"AccountID":7226088,"AccountGuid":"3a258272-3e3b-4db1-a9a2-1e04e341c2a5","Email":"","AvatarImage":"","GeocacheFindCount":113,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":340193177,"CacheID":3220672,"LogGuid":"2ae33e97-3a3a-425d-b7d8-3b621ea922d4","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Found it with K I N! ;)","Created":"2013-08-15","Visited":"2013-08-15","UserName":"Lilawal","MembershipLevel":1,"AccountID":7791384,"AccountGuid":"1fa5b881-0dbe-4a49-af65-959f899f4597","Email":"","AvatarImage":"4406d56f-9f00-4299-832c-d19411b2712d.jpg","GeocacheFindCount":12,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":335241565,"CacheID":3220672,"LogGuid":"2c6b924b-becd-4275-8e3d-509178f5f87e","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"TFTC <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" />","Created":"2013-08-02","Visited":"2013-08-02","UserName":"MrsJones*","MembershipLevel":1,"AccountID":7724546,"AccountGuid":"f4ef80f3-400f-408a-998a-dc17b846baed","Email":"","AvatarImage":"726bbd62-20ca-4fff-b4c3-62e9703ec306.jpg","GeocacheFindCount":11,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":331032294,"CacheID":3220672,"LogGuid":"59058647-41d3-4490-894f-eee93dfca51c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hzc! ","Created":"2013-07-18","Visited":"2013-07-18","UserName":"Pejntboks","MembershipLevel":1,"AccountID":7301367,"AccountGuid":"a0be7068-23e0-4cd0-8c17-72e9e781e802","Email":"","AvatarImage":"e91201a4-7e41-4cdd-bbec-ec53011538e6.gif","GeocacheFindCount":28,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":329487987,"CacheID":3220672,"LogGuid":"c2c9b364-2a08-47d6-9d1a-f0b716e054db","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Owner Maintenance","LogTypeImage":"46.png","LogText":"a while ago someone replaced the logbook and i promise i'll go and check on it soon<br /><br />Happy hunting","Created":"2013-07-13","Visited":"2013-07-13","UserName":"David & Ajda","MembershipLevel":3,"AccountID":5991956,"AccountGuid":"7b1ed479-e378-4cfd-a5b4-3bd47bab619f","Email":"","AvatarImage":"0bafa82b-6510-4903-bb6a-68dd455eb971.jpg","GeocacheFindCount":202,"GeocacheHideCount":15,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":328565685,"CacheID":3220672,"LogGuid":"029240c4-8daf-470e-871d-f46dfee2684c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hzz! <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" />","Created":"2013-07-09","Visited":"2013-07-09","UserName":"bremza","MembershipLevel":1,"AccountID":5283193,"AccountGuid":"7295459e-5262-43fa-8d4f-c8dd8ebf262e","Email":"","AvatarImage":"","GeocacheFindCount":162,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":328563478,"CacheID":3220672,"LogGuid":"9308486a-a2bf-48a6-820e-4d60f1ee21f0","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hvala za zaklad! <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" />","Created":"2013-07-09","Visited":"2013-07-09","UserName":"hropka","MembershipLevel":1,"AccountID":5307782,"AccountGuid":"0f5ad667-3900-440f-b5f3-8f0e76fc84a8","Email":"","AvatarImage":"","GeocacheFindCount":161,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":326820900,"CacheID":3220672,"LogGuid":"48b93040-aa09-4dce-a414-6c31e68a82de","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"TFTC","Created":"2013-07-03","Visited":"2013-07-03","UserName":"Svizec&Lisja","MembershipLevel":3,"AccountID":5666226,"AccountGuid":"a5c8fc25-6030-4313-942b-236a7cb4a1a1","Email":"","AvatarImage":"","GeocacheFindCount":203,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":325302896,"CacheID":3220672,"LogGuid":"2b8fc04d-2b49-414d-9f0c-ecae36a88cee","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Notri je veliko vode(za silo popravljeno) in malo mrtvih žužkov, drugaÄe pa zelo lepa lokacija in skrivaliÅ¡Äe. HZZ! :D","Created":"2013-06-27","Visited":"2013-06-27","UserName":"nosonje","MembershipLevel":1,"AccountID":5283276,"AccountGuid":"4a4fd997-0531-437c-baee-bb11272e5a12","Email":"","AvatarImage":"96cd321d-ab38-4bc1-bd8f-350d519c3ee5.jpg","GeocacheFindCount":120,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":323651478,"CacheID":3220672,"LogGuid":"98f9c80f-ecbf-437d-972c-9d82a71b950d","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"NaÅ¡la! Notri je voda in neki žužki! :)","Created":"2013-06-20","Visited":"2013-06-20","UserName":"hanaaa :)","MembershipLevel":1,"AccountID":7499579,"AccountGuid":"9a187938-a916-4759-9f9c-7bc6f1978468","Email":"","AvatarImage":"","GeocacheFindCount":15,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":320316919,"CacheID":3220672,"LogGuid":"b66fcfe6-9c54-479f-9323-334905eeb87e","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hitra najdba. :)<br /><br />Å katlica je res vlažna, vendar kot je že nekdo od predhodnikov povedal, logbook je varen :)<br /><br />HZZ","Created":"2013-06-07","Visited":"2013-06-05","UserName":"aljoG","MembershipLevel":1,"AccountID":6057040,"AccountGuid":"4b400d11-aea9-4305-95d4-928d96574d28","Email":"","AvatarImage":"","GeocacheFindCount":255,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":319969838,"CacheID":3220672,"LogGuid":"ae8e3d92-0407-421b-b1cf-ee798ea9ff42","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"V posodici je bila voda, a logbook je dobro zavarovan.<br />HZZ!","Created":"2013-06-05","Visited":"2013-06-05","UserName":"mmeglic","MembershipLevel":1,"AccountID":3716271,"AccountGuid":"86f8f1c6-fc72-495b-a32e-a4066ace063e","Email":"","AvatarImage":"60be750c-9ec4-439e-92bc-f77db5704ee3.bmp","GeocacheFindCount":459,"GeocacheHideCount":15,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":319749488,"CacheID":3220672,"LogGuid":"01cbe1c2-9061-408b-ad89-8ecc9aea05c3","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Sprehod po zelezniski tirih nas je pripeljal do novega zakladka.","Created":"2013-06-04","Visited":"2013-06-04","UserName":"Pustolovka","MembershipLevel":1,"AccountID":6986260,"AccountGuid":"a77cd22e-6dff-4240-bd7c-934bacc93625","Email":"","AvatarImage":"229d7f1c-4fc8-4594-b945-7daf04c28e8e.png","GeocacheFindCount":187,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":318121707,"CacheID":3220672,"LogGuid":"995ef24e-45c2-4786-b256-a236094138d8","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Could not log, because the box is totally wet inside. I attached a picture of the box as proof. Took out TB and saved it from drowning in the water. The box needs maintenance!<br /><br />This entry was edited by Larsus cisalpinus on Wednesday, 29 May 2013 at 21:33:36 UTC.","Created":"2013-05-29","Visited":"2013-05-29","UserName":"Larsus cisalpinus","MembershipLevel":3,"AccountID":7318481,"AccountGuid":"d3ced821-5969-4bca-89c6-2d74466dc6c8","Email":"","AvatarImage":"7613ed0e-6a52-4f54-9d90-be84be4d73f6.png","GeocacheFindCount":223,"GeocacheHideCount":11,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[{"ImageID":17960725,"ImageGuid":"1c3db698-e65d-4fa0-93d7-b72ccd9fda41","Name":"Zarascen tir 001","Descr":"","FileName":"1c3db698-e65d-4fa0-93d7-b72ccd9fda41.jpg","Created":"2013-05-29","LogID":318121707,"CacheID":3220672,"ImageUrl":null}]},{"LogID":317739701,"CacheID":3220672,"LogGuid":"8f07484c-ac82-4878-8716-bf182f584ad0","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hitro najdeno. In: TB<br />HZZ","Created":"2013-05-27","Visited":"2013-05-27","UserName":"hermani","MembershipLevel":3,"AccountID":1594587,"AccountGuid":"399778e5-6821-4c27-abe7-ca2df6a4c585","Email":"","AvatarImage":"","GeocacheFindCount":533,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":317728651,"CacheID":3220672,"LogGuid":"f3910ea4-5320-4d95-9d85-d4257828354f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"V Å¡katli je dosti vode, travel boy se utaplja, logbook pa je zaenkrat Å¡e suh.","Created":"2013-05-27","Visited":"2013-05-27","UserName":"geoscout_slo","MembershipLevel":3,"AccountID":6305970,"AccountGuid":"3919036d-5159-4227-9d81-0dd2188834b6","Email":"","AvatarImage":"4dc41fe7-8c11-4dad-9ef5-32f278195aaa.jpg","GeocacheFindCount":1116,"GeocacheHideCount":16,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":317262995,"CacheID":3220672,"LogGuid":"06fadc9e-f489-4122-ba51-12727e8cd24f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"During our trip by campingcar to Kroatië we found this cache<br /><br />TFTC Team Wans from the Netherlands","Created":"2013-05-26","Visited":"2013-05-26","UserName":"WANS","MembershipLevel":3,"AccountID":1982355,"AccountGuid":"69adeb9f-a5dd-4005-86d7-609250a3d4dc","Email":"","AvatarImage":"d90fbf86-39df-4376-8988-98c8188b23b4.jpg","GeocacheFindCount":2321,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":316856553,"CacheID":3220672,"LogGuid":"5d2e314f-d6ce-4151-8387-688104eaa35c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Didn't find it","LogTypeImage":"3.png","LogText":"Couldnt find it anywhere.... :(","Created":"2013-05-24","Visited":"2013-05-24","UserName":"idastante","MembershipLevel":1,"AccountID":5251559,"AccountGuid":"742b75c4-eb09-4dca-86f9-5e2b19fabbe5","Email":"","AvatarImage":"","GeocacheFindCount":75,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":316395131,"CacheID":3220672,"LogGuid":"6a847259-ba30-4817-a905-574efa416f16","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Å¡katlica je bila spet polna vode, logbook je suh.<br />HZZ!","Created":"2013-05-22","Visited":"2013-05-22","UserName":"Buhteljni","MembershipLevel":1,"AccountID":4407541,"AccountGuid":"dc0b3085-483c-48a9-a988-7846302fa721","Email":"","AvatarImage":"","GeocacheFindCount":745,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":314411680,"CacheID":3220672,"LogGuid":"212d0c53-0a27-47ae-8c17-fdf51255992c","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Ni kazalo drugega kot, da si izmislim en dober izgovor o nuji sprehoda po progi, Äe bi bil varnostnik kaj siten. Kot 90 predhodnikov je tudi meni ratalo brez problema. HZZ","Created":"2013-05-15","Visited":"2013-05-15","UserName":"marko0037","MembershipLevel":1,"AccountID":4062170,"AccountGuid":"df3a3244-64a0-4a56-97a9-e561178298ce","Email":"","AvatarImage":"e7b37399-a2d8-4350-809c-b2549409bf06.jpg","GeocacheFindCount":948,"GeocacheHideCount":66,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":315271823,"CacheID":3220672,"LogGuid":"c95d4dd3-4cca-404a-82bf-7957780aa9bc","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"The cache was full of water, but the loogbook was dry. We had no pencil to mark our visit in the logbook. For the evidence we made a photo of it. TFTC!","Created":"2013-05-19","Visited":"2013-05-12","UserName":"crimaldi","MembershipLevel":1,"AccountID":955257,"AccountGuid":"056f0a1f-9d75-4eac-8321-1da98dd07271","Email":"","AvatarImage":"f0bc05c9-5f68-4937-b8b7-8fceef1763ff.jpg","GeocacheFindCount":484,"GeocacheHideCount":10,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[{"ImageID":17818960,"ImageGuid":"43297a3c-de4c-4b70-a228-cdfe5b767094","Name":"Cache","Descr":"","FileName":"43297a3c-de4c-4b70-a228-cdfe5b767094.jpg","Created":"2013-05-19","LogID":315271823,"CacheID":3220672,"ImageUrl":null}]},{"LogID":313719869,"CacheID":3220672,"LogGuid":"7dc39404-2407-44a0-8298-29e03dfcfd9a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"HZZ","Created":"2013-05-12","Visited":"2013-05-12","UserName":"nixii","MembershipLevel":1,"AccountID":5786956,"AccountGuid":"d4964534-db4d-4d8a-8ec2-45e36ba6d3aa","Email":"","AvatarImage":"","GeocacheFindCount":77,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 119, "rows": 119 } }; -var gaToken = 'UA-2020240-1';//]]> -</script> -</form> - <script type="text/javascript"> - var browserType = { - IE: !!(window.attachEvent && !window.opera), - Opera: !!window.opera, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }; - - $(function () { - // Make the menu system play nice with all browsers: - $('ul.Menu li').hover(function () { - $(this).addClass('hover'); - $('ul:first', this).css('visibility', 'visible'); - }, function () { - $(this).removeClass('hover'); - $('ul:first', this).css('visibility', 'hidden'); - }); - if (!isiOS()) { - // Constructing a Twitter-esque Login: - $(".SignInLink").click(function (e) { - e.preventDefault(); - $("#SignInWidget").toggle(); - $(".ProfileWidget").toggleClass("WidgetOpen"); - $(this).blur(); - $("#ctl00_tbUsername").focus(); - $(document).click(function (e) { - if (!$(e.target).parents().hasClass("ProfileWidget")) { - $("#SignInWidget").hide(); - $(".ProfileWidget").removeClass("WidgetOpen"); - } - }); - return false; - }); - } - - if (!("placeholder" in document.createElement("input"))) { - $("#SignInWidget label").removeClass("hideMe"); - } - - $('.SignedInProfileLink').truncate({ - width: 120, - after: '&hellip;', - center: false, - addclass: false, - addtitle: false - }); - - // Hide the warning message if the user closed it already - if ($.cookie('hide_warning') != null) { - $(".WarningMessage").hide(); - } else { - $("#warningCloseButton").click(function () { - $('.WarningMessage').hide('blind'); - $.cookie('hide_warning', 'true', { expires: 1 }); - }); - } - - function isiOS() { - return ( - (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i)) - ); - } - }); - </script> +</script>
+ </section>
+
+ <section class="copyright">
+ <div class="container">
+ <p>
+ © 2000-2015
+ <a href="http://www.groundspeak.com/" title="Groundspeak, Inc." accesskey="g">Groundspeak, Inc.</a>
+ All Rights Reserved.
+ <a id="ctl00_hlFooterTerms" accesskey="u" title="Groundspeak Terms of Use" href="../about/termsofuse.aspx">Groundspeak Terms of Use</a>
+ |
+ <a id="ctl00_hlFooterPrivacy" accesskey="x" href="../about/privacypolicy.aspx">Privacy Policy</a>
+ </p>
+
+ <ul class="links-social">
+ <li>
+ <a id="ctl00_hlFacebook" title="Facebook" href="http://www.facebook.com/geocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlYouTube" title="YouTube" href="http://www.youtube.com/user/GoGeocaching"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlInstagram" title="Instagram" href="http://instagram.com/geocaching/"></a>
+ </li>
+ <li>
+ <a id="ctl00_hlTwitter" title="Twitter" href="http://twitter.com/GoGeocaching"></a>
+ </li>
+ </ul>
+ </div>
+ </section>
+ </footer>
+ <div class="SkipLinks">
+ <a id="ctl00_hlSkipLinksTop" accesskey="t" title="Return to the Top of the Page" href="#Top">Return to the Top of the Page</a>
+ </div>
+
+
+<script type="text/javascript">
+//<![CDATA[
+$(function() { _gaq.push(['_trackEvent', 'Geocaching', 'CacheDetailsMemberType', 'Premium', null, true]); });var isLoggedIn = true;
+mapLatLng = {"lat":46.08047,"lng":14.5,"type":2,"name":"ZaraÅ¡Äen Tir"};
+var ccConversions = [{"t":"Decimal","k":"DD","d":"WGS84","v":"46.080467, 014.500000"},{"t":"DDD MM SS.SSS","k":"DMS","d":"WGS84","v":"N 46° 04' 49.681\" E 014° 30' 00.000\""},{"t":"UTM","k":"UTM","d":"WGS84","v":"33T E 461340 N 5103109"}];
+var dh=false;userInfo = {ID: 3409138};
+userToken = 'ID5R2NBJDBPQYVKRP2QCKFMGOD72N345U34TRF3HIUOES7I3DEYZLGMWQENANSEL75TH743VWQXA4PRVBZVB2UFIVLT5HYFG73BJY737PC6AVOROLQCJBHWZ5WOPA4ZCUMZSO7RLBORYFW5XH4FZERAO4GV6P6EU7MMIJWSHJRI3VZ4OTYDT4GNLGNEWXCZDKFSNXO5UVQUQMS4XIY2MXUOUCQJGVQQ3CWWYBYS4LC22FGUVAUEA';
+includeAvatars = false;
+var lat=46.080467, lng=14.5, guid='51e40dec-6272-4dad-934b-e175daaac265';
+initalLogs = {"status":"success", "data": [{"LogID":471728564,"CacheID":3220672,"LogGuid":"7b2a1eb8-0399-4cb0-a768-05aa7abebc5a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Archive","LogTypeImage":"5.png","LogText":"Thanks.","Created":"2015-01-13","Visited":"2015-01-13","UserName":"Geolens Reviewer","MembershipLevel":3,"AccountID":778521,"AccountGuid":"b75a0c96-985c-416a-b472-2b37da5cc1ef","Email":"","AvatarImage":"7ada6f14-cae0-49d0-8888-1888bd8ec206.jpg","GeocacheFindCount":2,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Reviewer","GroupImageUrl":"/images/icon_admin.gif"},"Images":[]},{"LogID":465904435,"CacheID":3220672,"LogGuid":"fde8575b-4609-4057-a9fa-21b8c2ea6273","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Temporarily Disable Listing","LogTypeImage":"22.png","LogText":"Please do the maintanance on your cache and tell us if it is still there. I disable this cache for a month. <br /><br />After no response and another N/A log I have to archive it. Thanks.","Created":"2014-12-13","Visited":"2014-12-13","UserName":"Geolens Reviewer","MembershipLevel":3,"AccountID":778521,"AccountGuid":"b75a0c96-985c-416a-b472-2b37da5cc1ef","Email":"","AvatarImage":"7ada6f14-cae0-49d0-8888-1888bd8ec206.jpg","GeocacheFindCount":2,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Reviewer","GroupImageUrl":"/images/icon_admin.gif"},"Images":[]},{"LogID":465796393,"CacheID":3220672,"LogGuid":"9e8d2663-bd48-4344-88c1-9e144d801196","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Needs Archived","LogTypeImage":"7.png","LogText":"Cache has obviously disappeared a long time ago and cache owners are no longer active, do not respond to maintenance and NA requests at some of their other caches. It's time to let this one go...","Created":"2014-12-13","Visited":"2014-12-13","UserName":"icabrian","MembershipLevel":3,"AccountID":4405840,"AccountGuid":"a1b369e8-1f63-48d2-a45c-d315e1d207b2","Email":"","AvatarImage":"b2699ed1-5073-4a3c-81fa-96f4dc46d1ab.jpg","GeocacheFindCount":2565,"GeocacheHideCount":26,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":461333293,"CacheID":3220672,"LogGuid":"6b10f81b-cd78-4467-a4b4-d4dc62d93237","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Didn't find it","LogTypeImage":"3.png","LogText":"Iskali sva ga veÄ kot pol ure, brez uspeha. Bi pa lahko lastnik cacha preveril, Äe je sploh dostopen, glede na to, da so pred kratkim obrezovali drevesa in je na desni strani tirov ogromno težjih vej. LP","Created":"2014-11-15","Visited":"2014-11-15","UserName":"tabaluga1","MembershipLevel":1,"AccountID":10264789,"AccountGuid":"7ce3b363-5a9e-4875-b82f-fabc024fb92e","Email":"","AvatarImage":"","GeocacheFindCount":14,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":459732939,"CacheID":3220672,"LogGuid":"2a98a44b-ed9e-4ab2-a9de-e316ccab26d7","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Didn't find it","LogTypeImage":"3.png","LogText":"Kar nekaj Äasa iskal... ampak ga ni nikjer...","Created":"2014-11-08","Visited":"2014-11-08","UserName":"ŽKT","MembershipLevel":1,"AccountID":5797133,"AccountGuid":"d05bccf8-c730-4319-a97e-c7eff69a9bd5","Email":"","AvatarImage":"","GeocacheFindCount":808,"GeocacheHideCount":27,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":453019251,"CacheID":3220672,"LogGuid":"1876bacf-e6df-47b0-9357-e796cf0b3541","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Didn't find it","LogTypeImage":"3.png","LogText":"Iskali v temi..a vendar po pol ure obupali :(","Created":"2014-10-12","Visited":"2014-10-12","UserName":"KoalaSpela&JS","MembershipLevel":1,"AccountID":9349853,"AccountGuid":"7518eb15-a3d0-4619-aff0-2708e27f1056","Email":"","AvatarImage":"73901d9d-3a53-42d1-832b-712a8ba2bb8a.jpg","GeocacheFindCount":99,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":452817935,"CacheID":3220672,"LogGuid":"2db262aa-1002-4e94-9821-4934a64e8cfe","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Didn't find it","LogTypeImage":"3.png","LogText":"Nismo nasl. Pa smo pregledali vse polivinile in iskali vsaj pol ure. Ima kdo se kaksen namig?","Created":"2014-10-12","Visited":"2014-10-12","UserName":"jovoa","MembershipLevel":1,"AccountID":11022584,"AccountGuid":"9646cf3c-e2d2-4177-935a-8a3e2fcf9398","Email":"","AvatarImage":"","GeocacheFindCount":4,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":447814401,"CacheID":3220672,"LogGuid":"5f950efa-6e6e-4e77-b927-0b6bb324a48b","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Didn't find it","LogTypeImage":"3.png","LogText":"Napacen kesek sem ponesreci oznacila kot najdenega :( ko ga najdem ga bom pa dala kot najdenega :)","Created":"2014-09-23","Visited":"2014-09-24","UserName":"manca23","MembershipLevel":1,"AccountID":10465132,"AccountGuid":"ac9d054c-5d63-49ed-b4e0-fdabced68c9b","Email":"","AvatarImage":"f69e59d5-0709-4bcb-b65d-4efc63fb138d.jpg","GeocacheFindCount":83,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":447812068,"CacheID":3220672,"LogGuid":"1e136711-479d-493e-ae57-58aab66d8827","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Hitro :) le namig malce napacen :S tftc :)","Created":"2014-09-23","Visited":"2014-09-24","UserName":"manca23","MembershipLevel":1,"AccountID":10465132,"AccountGuid":"ac9d054c-5d63-49ed-b4e0-fdabced68c9b","Email":"","AvatarImage":"f69e59d5-0709-4bcb-b65d-4efc63fb138d.jpg","GeocacheFindCount":83,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":447740085,"CacheID":3220672,"LogGuid":"a1c195f1-1893-4977-b7b4-803e28ba2c19","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Tftc. Po petem poizkusu smo ga konÄno naÅ¡li. Gps kaže dejansko 4m stran. Pomagala slikca in odvržen polivinil . ","Created":"2014-09-23","Visited":"2014-09-23","UserName":"morfej","MembershipLevel":1,"AccountID":9159065,"AccountGuid":"74daad71-4bc2-458e-a92c-e0830f46544a","Email":"","AvatarImage":"8febeb81-6dc4-4621-be01-e70e2674ed06.jpg","GeocacheFindCount":425,"GeocacheHideCount":4,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":447714784,"CacheID":3220672,"LogGuid":"77105f59-b874-4087-b490-fc84d9eedc8e","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"fak zafrknn do konca!!! :D ampak nice!!","Created":"2014-09-23","Visited":"2014-09-23","UserName":"blackwings1","MembershipLevel":1,"AccountID":10582292,"AccountGuid":"43046d5d-b9d5-4b51-95eb-2e3df1969594","Email":"","AvatarImage":"c323fa2d-e6ec-4628-9964-eb3f2a281fbe.jpeg","GeocacheFindCount":145,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":465449211,"CacheID":3220672,"LogGuid":"f3661d40-fb39-4f44-86aa-aae9c367ceef","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"That’s one more find for me! Thanks so much for hiding this geocache.","Created":"2014-12-09","Visited":"2014-09-20","UserName":"kjerkloe","MembershipLevel":1,"AccountID":10158843,"AccountGuid":"6b9ba8da-6090-4ff2-ae4f-2c85a0ede0fe","Email":"","AvatarImage":"","GeocacheFindCount":92,"GeocacheHideCount":1,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":446668838,"CacheID":3220672,"LogGuid":"fc9161ae-9818-47f0-8d4e-f155b90884e9","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"PonoÄi je malo težje ga najti, pa vendarle sva ga opazili. HZZ! :) <br />Logbook je premoÄen in potreben zamenjave, saj prostora ni veÄ-sva se podpisali na zadnjo stran.","Created":"2014-09-20","Visited":"2014-09-19","UserName":"zelenko&ana","MembershipLevel":3,"AccountID":9650533,"AccountGuid":"17fb56c6-5196-44e4-9867-9002c13b8a05","Email":"","AvatarImage":"cba51b72-6696-4f5a-9cdb-2382c18e2895.jpg","GeocacheFindCount":494,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":445228772,"CacheID":3220672,"LogGuid":"d8bb2888-36d9-4a8e-abe1-a280c7881fbf","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Po kar dolgem iskanju smo ga naÅ¡li. Frnikulo zamenjali z avtomobilÄkom.<br />Hzz","Created":"2014-09-14","Visited":"2014-09-14","UserName":"ZipBlocx","MembershipLevel":1,"AccountID":9321945,"AccountGuid":"ec68a9b1-2a12-42c6-94a7-8fb15c60b74c","Email":"","AvatarImage":"","GeocacheFindCount":2,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":443418219,"CacheID":3220672,"LogGuid":"af60d92b-1739-4899-88f9-c809ef669c09","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"VeÄerni potep s kolesom.<br /><br />HZZ","Created":"2014-09-07","Visited":"2014-09-07","UserName":"bbajs","MembershipLevel":3,"AccountID":10525211,"AccountGuid":"f0dad178-d784-4f88-8acc-bc9c572f2b38","Email":"","AvatarImage":"56a461cd-479f-4a07-b4ed-bbfdabb0000d.jpg","GeocacheFindCount":429,"GeocacheHideCount":6,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[{"ImageID":24389373,"ImageGuid":"03662b37-6376-461b-99f7-531b41ee3354","Name":"","Descr":"","FileName":"03662b37-6376-461b-99f7-531b41ee3354.jpg","Created":"2014-09-07","LogID":443418219,"CacheID":3220672,"ImageUrl":null}]},{"LogID":441923337,"CacheID":3220672,"LogGuid":"f33fcfa4-dbd6-4fc9-9ff1-65f2459aabca","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Zanimiv zaklad, pokrov Å¡katlice zlomljen:(<br />HZZ","Created":"2014-09-02","Visited":"2014-09-02","UserName":"rozica","MembershipLevel":3,"AccountID":10546480,"AccountGuid":"64333e98-d178-4dd9-b6e0-1b51cc4abff9","Email":"","AvatarImage":"0a336011-3981-4191-8304-d80c35152b22.jpg","GeocacheFindCount":283,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":440060287,"CacheID":3220672,"LogGuid":"8ba61aec-340d-4ed3-a237-93f6ab3e6891","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Tukaj sva se s Tjanom že drugiÄ danes sreÄala in Å¡ele tukaj ugotovila, da nisva tujca in da se lahko pogovarjava tudi v slovenÅ¡Äini. :) OÄitno sva se prej narobe razumela. Združila sva moÄi, a to ni zadostovalo. Po klicu v sili, je bilo iskanje nekoliko bolj enostavno. <br />Opis cacha mi sicer deluje malo zmedeno. Vem, da je bil nek del teksta zaradi reklame odstranjen, a sedaj nam oÄitno kadar zbolimo pomaga zaraÅ¡Äen tir?<br />TFTC","Created":"2014-08-28","Visited":"2014-08-28","UserName":"pograd","MembershipLevel":1,"AccountID":5281767,"AccountGuid":"0ca3d5b4-8823-4a96-a5a6-36ba74b602be","Email":"","AvatarImage":"2a462ee7-9cb8-4d9b-9ff8-d26cd2f76617.jpg","GeocacheFindCount":783,"GeocacheHideCount":6,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":440027024,"CacheID":3220672,"LogGuid":"19788564-e0bb-49bc-96e8-6be1b523f9ae","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Under the brown! ","Created":"2014-08-28","Visited":"2014-08-28","UserName":"Tjan","MembershipLevel":1,"AccountID":10374351,"AccountGuid":"808f84d5-7d33-48e3-acfc-783e08c8050b","Email":"","AvatarImage":"1f4f8987-c992-4eca-bc2a-a123c67624bc.jpeg","GeocacheFindCount":164,"GeocacheHideCount":2,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":439165288,"CacheID":3220672,"LogGuid":"8ad3f6b4-23ac-4726-8453-1b17a1ecdf7a","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Found together with sierius, thx for hiding.<br />TFTC<br />harrylime + Ingrid","Created":"2014-08-25","Visited":"2014-08-23","UserName":"harrylime","MembershipLevel":3,"AccountID":1195360,"AccountGuid":"630f3b79-023a-4908-b960-143eaca19f99","Email":"","AvatarImage":"53fbcfa7-8e53-49f6-bbe1-8c7d8c3b27a7.jpg","GeocacheFindCount":29119,"GeocacheHideCount":28,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":438323373,"CacheID":3220672,"LogGuid":"50aadeb0-c2d2-4f25-9ec7-47ce11a932f5","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Found together with harrylime.<br />Thanks for hiding to all owners and greetings from Austria!<br />SIERIUS","Created":"2014-08-23","Visited":"2014-08-23","UserName":"SIERIUS","MembershipLevel":3,"AccountID":1609892,"AccountGuid":"36495b95-d980-49af-919d-a132fcd4726e","Email":"","AvatarImage":"c15f228a-4b20-4f8d-9a63-3c0ad9e9d3f4.jpg","GeocacheFindCount":23896,"GeocacheHideCount":29,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":432414556,"CacheID":3220672,"LogGuid":"1b80b42f-761a-4e4b-a616-a2564cee3869","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Ne kup, polivinil ga je izdal. Standardni postopek, odlij vodo in vpisi. Zdaj sem Å¡katlo obrnil na glavo.<br /><br />Not stones but PVC revealed this one.<br /><br />TFTC!","Created":"2014-08-07","Visited":"2014-08-07","UserName":"Bamzž","MembershipLevel":3,"AccountID":1631613,"AccountGuid":"cea0e22f-d997-498b-b1aa-d2a6e967bf28","Email":"","AvatarImage":"","GeocacheFindCount":1217,"GeocacheHideCount":8,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Premium Member","GroupImageUrl":"/images/icons/prem_user.gif"},"Images":[]},{"LogID":430573248,"CacheID":3220672,"LogGuid":"6aee7c80-90fa-4851-aa33-80f5f0edb7a1","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Iskal 30 m","Created":"2014-08-02","Visited":"2014-08-02","UserName":"Possessor","MembershipLevel":1,"AccountID":5457171,"AccountGuid":"04336896-c32d-464f-8be2-3c4e4f16f42d","Email":"","AvatarImage":"","GeocacheFindCount":27,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":401779621,"CacheID":3220672,"LogGuid":"21c0ce48-3d19-47b7-83dc-901fbe1e08b8","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Tudi notranji kontejner je moker :( Je pa super izvedba <br />Out: kompasek<br />In: frnikula<br /><br />HZZ, 5M (4/5)","Created":"2014-04-27","Visited":"2014-04-27","UserName":"5M-jev","MembershipLevel":1,"AccountID":9137542,"AccountGuid":"fadeae0f-e52f-45ac-af65-f073d84db2ad","Email":"","AvatarImage":"8ea519e3-163e-4d03-bfdb-47a400d66ee6.jpg","GeocacheFindCount":43,"GeocacheHideCount":0,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":400178423,"CacheID":3220672,"LogGuid":"53e6769c-6538-4d96-aa58-592c244d0ee7","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Kot moji predhodniki sem tudi jaz najprej odlil vodo, nato pa se lotil vpisa v dnevnik, ki je bil tudi precej vlažen. PriporoÄam menjavo posode.<br /><br />HZZ!","Created":"2014-04-22","Visited":"2014-04-22","UserName":"IztokCult","MembershipLevel":1,"AccountID":1229391,"AccountGuid":"8ef811cb-1e14-4147-ad9c-999daedc6c72","Email":"","AvatarImage":"","GeocacheFindCount":212,"GeocacheHideCount":3,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]},{"LogID":399535262,"CacheID":3220672,"LogGuid":"b0282337-123f-43e8-aebb-f555ea946b8f","Latitude":null,"Longitude":null,"LatLonString":"","LogType":"Found it","LogTypeImage":"2.png","LogText":"Po tem ko sem napolnil rezervoar v avtu sem se ustavil Å¡e pri tem zakladu. Kljub temu, da je daž zaÄel moÄneje padati ravno, ko sem stopil iz avta, sem vzel Å¡e dežnik. Zaklad mi je uspelo hitro najti. V njem je bilo veliko vode, vendar pa je dnevnik ostal skoraj Äisto suh, ker je votranja posodica dobra <img src=\"/images/icons/icon_smile.gif\" border=\"0\" align=\"middle\" /><br />HZZ","Created":"2014-04-21","Visited":"2014-04-21","UserName":"vasili1945","MembershipLevel":1,"AccountID":7808645,"AccountGuid":"69cfa81a-4743-4ac4-a27e-16bdad245ce4","Email":"","AvatarImage":"dfe29348-335e-4d78-bab7-4d8de589326a.jpg","GeocacheFindCount":1994,"GeocacheHideCount":52,"ChallengesCompleted":0,"IsEncoded":false,"creator":{"GroupTitle":"Member","GroupImageUrl":"/images/icons/reg_user.gif"},"Images":[]}], "pageInfo": { "idx":1, "size": 25, "totalRows": 175, "rows": 175 } };
+var gaToken = 'UA-2020240-1';ga('create', 'UA-2020240-35', 'geocaching.com'); ga('send', 'pageview');//]]>
+</script>
+</form>
+ <script src="/js/jquery_plugins/tinynav.min.js"></script>
+ <script src="/js/matchMedia.js"></script>
+ <script src="/account/scripts/custom/message-center-header-widget.js"></script>
+ <script>
+ $('#messagecenterheaderwidget').messageCenterHeaderWidget();
+
+ var browserType = {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ };
+
+ // Modernizr only identifies browsers that support touch events; Windows Phone and webOS handle touch differently
+ var isMobile = (/(webOS|hpwOS|IEMobile)/).test(navigator.userAgent);
+
+ $(function () {
+ var $topMenuLinks = $('.Menu > li');
+
+ $topMenuLinks.children('a').each(function () {
+ $(this).on('touchstart click', function (e) {
+ e.stopPropagation();
+
+ var $this = $(this),
+ $parent = $(this).parent();
+
+ $topMenuLinks.removeClass('hover');
+
+ if (!$parent.hasClass('hover') && $this.hasClass('Dropdown')) {
+ e.preventDefault();
+ $parent.addClass('hover');
+ }
+ });
+ });
+
+ var $userMenuBtn = $('.logged-in-user .li-user-toggle');
+
+ $userMenuBtn.on('touchstart click', function (e) {
+ e.stopPropagation();
+ $(this).next('ul').addClass('user-expanded');
+ });
+
+ $(document).on('click', function (e) {
+ if ($('.user-expanded').length && !$(e.target).parents().hasClass("user-expanded")) {
+ $('.user-expanded').removeClass("user-expanded");
+ }
+ if (!$(e.target).parents().hasClass("Menu")) {
+ $topMenuLinks.removeClass("hover");
+ }
+ });
+
+ if (isMobile || Modernizr.touch) {
+ // Convert language dropdown to native select
+ $("ul.language-list .selected").parent().addClass("selected");
+ $(".selected-language a, ul.language-list").hide();
+ $(".language-list").tinyNav({
+ active: 'selected'
+ });
+ }
+
+
+ // Constructing a Twitter-esque Login:
+ $(".SignInLink").on('click', function (e) {
+ if (window.matchMedia("(min-width: 1000px)").matches) {
+ e.preventDefault();
+ $("#SignInWidget").toggle();
+ $(".ProfileWidget").toggleClass("WidgetOpen");
+ $(this).blur();
+ $("#ctl00_tbUsername").focus();
+ $(document).click(function (e) {
+ if (!$(e.target).parents().hasClass("ProfileWidget")) {
+ $("#SignInWidget").hide();
+ $(".ProfileWidget").removeClass("WidgetOpen");
+ }
+ });
+ return false;
+ }
+ });
+
+
+ if (!("placeholder" in document.createElement("input"))) {
+ $("#SignInWidget label").removeClass("hideMe");
+ }
+
+ // Hide the warning message if the user closed it already
+ if ($.cookie('hide_warning') != null) {
+ $(".WarningMessage").hide();
+ } else {
+ $("#warningCloseButton").click(function () {
+ $('.WarningMessage').hide('blind');
+ $.cookie('hide_warning', 'true', { expires: 1 });
+ });
+ }
+
+ function isiOS() {
+ return (
+ (navigator.userAgent.match(/(iPhone)|(iPod)|(iPad)/i))
+ );
+ }
+ });
+ </script>
<script type="text/javascript"> <!-- @@ -1410,9 +1317,8 @@ var gaToken = 'UA-2020240-1';//]]> var editLink = $('a[href*="report.aspx"]').attr('href'); - $("#cspMessage").prepend('<P>Please take a moment to check the listing and ensure it is ready to enable. Clicking "Submit for Review" will enable your cache page.</P>'); - $("#cspMessage").prepend('<P>Once it is enabled, you will receive a confirmation email that it was successfully submitted. It is peak season for cache placement. Your volunteer reviewer will strive to begin the review process within the next 7 days.</P>'); - $("#cspMessage").prepend('<P>Your cache page has not been reviewed yet. It will not appear in the review queue until you enable it.</P>'); + $("#cspMessage").prepend('<P><strong>Already submitted this geocache?</strong> Please check below for the Reviewer’s notes and make any necessary changes before you resubmit. You can also respond by clicking "Log Your Visit" and posting a Reviewer Note.</P>'); + $("#cspMessage").prepend('<P>Your geocache has not been published. Once your geocache is in place and all of the details have been entered, click "Submit for Review". A volunteer reviewer will begin the review process within about 7 days.</P>'); $("#cspGoBack").click(function (e) { e.preventDefault(); @@ -1433,15 +1339,7 @@ var gaToken = 'UA-2020240-1';//]]> return false; }); - $("#cspConfirm").change(function() { - if ($("#cspConfirm").is(":checked")) { - $("#cspSubmit").removeAttr('disabled'); - $("#cspGoBack").attr('disabled', true); - } else { - $("#cspSubmit").attr('disabled', true); - $("#cspGoBack").removeAttr('disabled'); - } - }); + } @@ -1529,7 +1427,7 @@ var gaToken = 'UA-2020240-1';//]]> $(this).countable({ maxLength: 500 }); - } + } }); $("#pcn_help").qtip({ @@ -1542,6 +1440,7 @@ var gaToken = 'UA-2020240-1';//]]> classes: 'ui-tooltip-dark ui-tooltip-rounded pcn-tooltip' }, }); + $("a.decrypt-link").html(decryptLogs ? locString.encrypt : locString.decrypt); if ($("#cache_logs_container").length > 0) { @@ -1633,14 +1532,16 @@ var gaToken = 'UA-2020240-1';//]]> return false; }); + $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({ + overlayShow: false + }); + setStaticMaps(); - //$("#staticMap").lazyload(); } }); function setStaticMaps() { - var llBounds = new L.LatLngBounds(); - + var map = new L.Map('map_preview_canvas', { center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), zoom: 10, @@ -1652,8 +1553,8 @@ var gaToken = 'UA-2020240-1';//]]> }) .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })); - var mapLarge = new L.Map('map_canvas', { - center: new L.LatLng(mapLatLng.lat, mapLatLng.lng), + var mapLarge = L.map('map_canvas', { + center: [mapLatLng.lat, mapLatLng.lng], zoom: 14, doubleClickZoom: true, dragging: true, @@ -1663,23 +1564,22 @@ var gaToken = 'UA-2020240-1';//]]> attributionControl: false }) .addControl(new L.Control.Attribution({ prefix: '<a href="/about/maps.aspx#leaflet" target="_blank">About our maps</a>' })) - .addControl(new L.Control.Scale()); - - llBounds.extend(new L.LatLng(mapLatLng.lat, mapLatLng.lng)); + .addControl(new L.Control.Scale()); var tileOptions = { - tileUrl: "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg", - name: "mpqosm", - alt: "MapQuest", - //attribution: "Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>, Map and map data © 2012 <a href=\"http://www.openstreetmap.org\" target='_blank'>OpenStreetMap</a> and contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>. ", + tileUrl: "https://otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg", + //name: "mpqosm", + //alt: "MapQuest", subdomains: "1234", - tileSize: 256, + //tileSize: 256, minZoom: 0, maxZoom: 18 }; - map.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions)); - mapLarge.addLayer(new L.TileLayer(tileOptions.tileUrl, tileOptions)); + map.addLayer(L.tileLayer(tileOptions.tileUrl, tileOptions)); + + L.tileLayer(tileOptions.tileUrl, tileOptions) + .addTo(mapLarge); var pinIcon = L.Icon.extend({ iconSize: new L.Point(20, 23), @@ -1697,36 +1597,37 @@ var gaToken = 'UA-2020240-1';//]]> return false; }); - var mkA2 = new L.Marker(new L.LatLng(mapLatLng.lat, mapLatLng.lng), { - icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + mapLatLng.type + '.png', iconAnchor: new L.Point(10,23)}), - clickable: false, zIndexOffset:99, title: mapLatLng.name - }); + L.marker([mapLatLng.lat, mapLatLng.lng], { + icon: L.icon({iconUrl: '/images/wpttypes/pins/' + mapLatLng.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23]}), + clickable: false, + //zIndexOffset: 99, + title: mapLatLng.name + }).addTo(mapLarge); map.addLayer(mkA); - mapLarge.addLayer(mkA2); - - $("#ctl00_ContentBody_uxNotesAboutPrinting").fancybox({ - overlayShow: false - }); if (cmapAdditionalWaypoints != null && cmapAdditionalWaypoints.length > 0) { + var llBounds = L.latLngBounds([mapLatLng.lat, mapLatLng.lng], [mapLatLng.lat, mapLatLng.lng]); + for (var x = 0, len = cmapAdditionalWaypoints.length; x < len; x++) { - + var item = cmapAdditionalWaypoints[x], - ll = new L.LatLng(item.lat, item.lng), - marker = new L.Marker(ll, { - icon: new pinIcon({iconUrl:'/images/wpttypes/pins/' + item.type + '.png', iconAnchor: new L.Point(10,23)}), - title: item.name, - clickable:false - }); + ll = [item.lat, item.lng]; + + L.marker(ll, { + icon: L.icon({ iconUrl: '/images/wpttypes/pins/'+ item.type + '.png', iconSize: [20, 23], iconAnchor: [10, 23] }), + title: item.name, + clickable: false + }).addTo(mapLarge); llBounds.extend(ll); - mapLarge.addLayer(marker); } - var bz = mapLarge.getBoundsZoom(llBounds.pad(1.1)); - - mapLarge.setView(new L.LatLng(mapLatLng.lat, mapLatLng.lng), bz); + + window.setTimeout(function () { + mapLarge.fitBounds(llBounds.pad(.5)); + }, 100); + } } @@ -1876,11 +1777,13 @@ var gaToken = 'UA-2020240-1';//]]> var score = 0; - if(scoreResult) + if(scoreResult) { score = scoreResult; + } - if(score > 100) + if(score > 100) { score = 100; + } $('#imgFavoriteScore').attr('src', '/images/favorites/piecharts/' + score + '.png'); var pieDesc = (score < 1 ? "<1" : score) + '% ' + $("#loc_favPointsScoreDesc").text().trim(); @@ -1894,7 +1797,13 @@ var gaToken = 'UA-2020240-1';//]]> }); } var scrollId = false, + logTop = 0; + + if (document.getElementById("cache_logs_container") != null){ logTop = $("#cache_logs_container").position().top; + } + + $(window).on("scroll", function() { if (scrollId != false) { window.clearTimeout(scrollId); @@ -1919,10 +1828,6 @@ var gaToken = 'UA-2020240-1';//]]> favContainer.removeClass('favorite-container-open'); }); } - if ($('#log-dropdown-options').is(':visible') && !$clicked.parents().hasClass('Dropdown')){ - $('#log-dropdown-options').toggleClass('hideMe'); - $('.Dropdown').toggleClass('Active'); - } }); $('#uxFavContainerLink').click(function () { @@ -1943,71 +1848,62 @@ var gaToken = 'UA-2020240-1';//]]> } }); - $('#dropdown-arrow').on('click', function(e){ - e.preventDefault(); - $('#log-dropdown-options').toggleClass('hideMe'); - $('.Dropdown').toggleClass('Active'); - }); // End --> </script> - - <script type="text/javascript"> - $(document).ready(function () { - $('#hlUpgrade').bind('click', function () { - var _this = $(this); - _gaq.push(['_trackEvent', 'Geocaching', 'Premium Upsell', 'Mini-profile Widget']); - setTimeout(function () { // Chrome requires a slight delay for tracking to fire. - window.location.href = _this.attr('href'); - }, 100); - return false; - }); - }); - </script> - <script type="text/javascript"> - _gaq.push(['_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js']); - _gaq.push(['_setAccount', gaToken]); - _gaq.push(['_trackPageview']); - (function () { - var ga = document.createElement('script'); - ga.src = ('https:' == document.location.protocol ? - 'https://ssl' : 'http://www') + - '.google-analytics.com/ga.js'; - ga.setAttribute('async', 'true'); - document.documentElement.firstChild.appendChild(ga); - })(); - $(function () { - $("a.language").click(function (e) { - e.preventDefault(); - window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang")); - }); - }); - </script> - <!-- Quantcast Tag --> - <div id="Quantcast"> - <script type="text/javascript"> - var _qevents = _qevents || []; - - (function () { - var elem = document.createElement('script'); - - elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js"; - elem.async = true; - elem.type = "text/javascript"; - var scpt = document.getElementsByTagName('script')[0]; - scpt.parentNode.insertBefore(elem, scpt); - })(); - </script> - <script type="text/javascript"> - _qevents.push({ qacct: "p-f6VPrfmR4cujU" }); - </script> - <noscript> - <div style="display: none;"> - <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1" - alt="Quantcast" /> - </div> - </noscript> - </div> - <!-- End Quantcast tag --> - <!-- Server: WEB17; Build: Web.HotFix_20130821.1 --> -</body> -</html> +
+
+ <script type="text/javascript">
+
+
+ $(document).ready(function () {
+ $('#hlUpgrade').bind('click', function () {
+ var _this = $(this);
+ _gaq.push(['_trackEvent', 'Geocaching', 'Premium Upsell', 'Mini-profile Widget']);
+ setTimeout(function () { // Chrome requires a slight delay for tracking to fire.
+ window.location.href = _this.attr('href');
+ }, 100);
+ return false;
+ });
+ });
+
+
+ _gaq.push(['_setCustomVar', 1, 'AccountId', 3409138, 1]);
+
+
+ _gaq.push(['_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js']);
+ _gaq.push(['_setAccount', gaToken]);
+ _gaq.push(['_trackPageview']);
+
+ $(function () {
+ $("a.language").click(function (e) {
+ e.preventDefault();
+ window.location.replace(window.location.href + (window.location.search.indexOf("?") == -1 ? "?" : "&") + "lang=" + $(this).attr("lang"));
+ });
+ });
+
+ var _qevents = _qevents || [];
+ _qevents.push({ qacct: "p-f6VPrfmR4cujU" });
+
+ (function () {
+ var elem = document.createElement('script');
+
+ elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+ elem.async = true;
+ elem.type = "text/javascript";
+ var scpt = document.getElementsByTagName('script')[0];
+ scpt.parentNode.insertBefore(elem, scpt);
+ })();
+
+
+
+ </script>
+ <noscript>
+ <div style="display: none;">
+ <img src="http://pixel.quantserve.com/pixel/p-f6VPrfmR4cujU.gif" height="1" width="1"
+ alt="Quantcast" />
+ </div>
+ </noscript>
+ <!-- Server: WEB07; Build: Tucson.Main.release-20150330.1.Release_270
+ -->
+</body>
+</html>
diff --git a/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java b/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java index 65de80c..e282881 100644 --- a/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java +++ b/tests/src/cgeo/geocaching/test/mock/GC3XX5J.java @@ -4,7 +4,10 @@ import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; +import cgeo.geocaching.settings.Settings; + +import org.eclipse.jdt.annotation.NonNull; import java.text.ParseException; import java.util.Date; @@ -38,6 +41,7 @@ public class GC3XX5J extends MockedCache { return "David & Ajda"; } + @NonNull @Override public CacheSize getSize() { return CacheSize.SMALL; @@ -55,9 +59,11 @@ public class GC3XX5J extends MockedCache { @Override public boolean isArchived() { - return false; + // The cache has been archived since 2015-01-13. + return true; } + @NonNull @Override public String getOwnerUserId() { return "David & Ajda"; @@ -93,6 +99,7 @@ public class GC3XX5J extends MockedCache { return null; } + @NonNull @Override public List<String> getAttributes() { final String[] attributes = new String[] { @@ -133,4 +140,10 @@ public class GC3XX5J extends MockedCache { public String getShortDescription() { return "Kadar zbolimo nam pomaga...<br /> <br /> When we get sick, they are helpful..."; } + + @Override + public boolean isFound() { + return Settings.getUsername().equals("mucek4"); + } + } diff --git a/tests/src/cgeo/geocaching/test/mock/MockedCache.java b/tests/src/cgeo/geocaching/test/mock/MockedCache.java index cd482f8..1981283 100644 --- a/tests/src/cgeo/geocaching/test/mock/MockedCache.java +++ b/tests/src/cgeo/geocaching/test/mock/MockedCache.java @@ -2,28 +2,30 @@ package cgeo.geocaching.test.mock; import static org.assertj.core.api.Assertions.assertThat; -import cgeo.geocaching.ICache; +import cgeo.geocaching.Geocache; import cgeo.geocaching.Image; import cgeo.geocaching.Trackable; import cgeo.geocaching.connector.gc.GCConstants; -import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.utils.TextUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import org.mapsforge.core.IOUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.Collections; import java.util.List; import junit.framework.Assert; -public abstract class MockedCache implements ICache { +public abstract class MockedCache extends Geocache { final protected Geopoint coords; - private String data; + private final String data; private String mockedDataUser; protected MockedCache(final Geopoint coords) { @@ -38,13 +40,13 @@ public abstract class MockedCache implements ICache { return mockedDataUser; } - public void setMockedDataUser(String mockedDataUser) { + public void setMockedDataUser(final String mockedDataUser) { this.mockedDataUser = mockedDataUser; assertThat(StringUtils.isNotBlank(this.mockedDataUser)).isTrue(); } public static String getDateFormat() { - return "dd/MM/yyyy"; + return "yyyy-MM-dd"; } /* @@ -71,7 +73,7 @@ public abstract class MockedCache implements ICache { } return TextUtils.replaceWhitespace(buffer.toString()); - } catch (IOException e) { + } catch (final IOException e) { Assert.fail(e.getMessage()); } finally { IOUtils.closeQuietly(is); @@ -141,8 +143,9 @@ public abstract class MockedCache implements ICache { } @Override + @NonNull public List<Image> getSpoilers() { - return null; + return Collections.emptyList(); } @Override diff --git a/tests/src/cgeo/geocaching/utils/DateUtilsTest.java b/tests/src/cgeo/geocaching/utils/CalendarUtilsTest.java index d0a2b4a..c074903 100644 --- a/tests/src/cgeo/geocaching/utils/DateUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/CalendarUtilsTest.java @@ -5,17 +5,17 @@ import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheType; -import java.util.Calendar; - import junit.framework.TestCase; -public class DateUtilsTest extends TestCase { +import java.util.Calendar; + +public class CalendarUtilsTest extends TestCase { public static void testDaysSince() { final Calendar start = Calendar.getInstance(); for (int hour = 0; hour < 24; hour++) { start.set(Calendar.HOUR_OF_DAY, hour); - assertThat(DateUtils.daysSince(start.getTimeInMillis())).isEqualTo(0); + assertThat(CalendarUtils.daysSince(start.getTimeInMillis())).isEqualTo(0); } } @@ -32,12 +32,22 @@ public class DateUtilsTest extends TestCase { assertPastEvent(start, true); } - private static void assertPastEvent(final Calendar start, boolean expectedPast) { + private static void assertPastEvent(final Calendar start, final boolean expectedPast) { final Geocache cache = new Geocache(); cache.setType(CacheType.EVENT); cache.setHidden(start.getTime()); - assertThat(DateUtils.isPastEvent(cache)).isEqualTo(expectedPast); + assertThat(CalendarUtils.isPastEvent(cache)).isEqualTo(expectedPast); } + public static void testIsFuture() { + final Calendar date = Calendar.getInstance(); + assertThat(CalendarUtils.isFuture(date)).isFalse(); + + date.add(Calendar.DAY_OF_MONTH, 1); + assertThat(CalendarUtils.isFuture(date)).isFalse(); + + date.add(Calendar.DAY_OF_MONTH, 1); + assertThat(CalendarUtils.isFuture(date)).isTrue(); + } } diff --git a/tests/src/cgeo/geocaching/utils/CheckerUtilsTest.java b/tests/src/cgeo/geocaching/utils/CheckerUtilsTest.java new file mode 100644 index 0000000..fa7c7e7 --- /dev/null +++ b/tests/src/cgeo/geocaching/utils/CheckerUtilsTest.java @@ -0,0 +1,25 @@ +package cgeo.geocaching.utils; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.Geocache; + +import junit.framework.TestCase; + +public class CheckerUtilsTest extends TestCase { + + public static void testGetCheckerUrl() throws Exception { + assertUrl("<p style=\"text-align:center;\"><a href=\"http://geocheck.org/geo_inputchkcoord.php?gid=618932716cc7e68-c4bb-4f41-8bb1-3e0a3e374a1f\" target=\"_blank\"><img", "http://geocheck.org/geo_inputchkcoord.php?gid=618932716cc7e68-c4bb-4f41-8bb1-3e0a3e374a1f"); + assertUrl("<p style=\"text-align:center;\"><a href=\"http://google.com/geo_inputchkcoord.php?gid=618932716cc7e68-c4bb-4f41-8bb1-3e0a3e374a1f\" target=\"_blank\"><img", null); + assertUrl("http://www.certitudes.org/certitude?wp=GC5MVX7", "http://www.certitudes.org/certitude?wp=GC5MVX7"); + assertUrl("http://geochecker.com/index.php?code=e001928e3c2682ec2bae0f24b9d02cfb&action=check&wp=474350573454&name=47656f636865636b6572205465737420666f72204e33382030302e303030205737362030302e303030", "http://geochecker.com/index.php?code=e001928e3c2682ec2bae0f24b9d02cfb&action=check&wp=474350573454&name=47656f636865636b6572205465737420666f72204e33382030302e303030205737362030302e303030"); + assertUrl("<p>Haarige Aussichten gibt es <a href=\"http://www.geochecker.com/index.php?code=cd52752a8649c5e385a624b5341176f9&action=check&wp=4743314a43384b&name=4b61747a656e&language=German\">hier</a>.</p></span>", "http://www.geochecker.com/index.php?code=cd52752a8649c5e385a624b5341176f9&action=check&wp=4743314a43384b&name=4b61747a656e&language=German"); + } + + private static void assertUrl(final String description, final String expected) { + final Geocache geocache = new Geocache(); + geocache.setDescription(description); + assertThat(CheckerUtils.getCheckerUrl(geocache)).isEqualTo(expected); + } + +} diff --git a/tests/src/cgeo/geocaching/utils/FileUtilsTest.java b/tests/src/cgeo/geocaching/utils/FileUtilsTest.java new file mode 100644 index 0000000..65638e1 --- /dev/null +++ b/tests/src/cgeo/geocaching/utils/FileUtilsTest.java @@ -0,0 +1,49 @@ +package cgeo.geocaching.utils; + +import static org.assertj.core.api.Assertions.assertThat; + +import cgeo.geocaching.files.LocalStorage; + +import junit.framework.TestCase; + +import java.io.File; +import java.io.IOException; + +public class FileUtilsTest extends TestCase { + + final File testDir = LocalStorage.getStorageDir("automated-tests"); + final File baseFile = new File(testDir, "prefix.ext"); + final File alternative1 = new File(testDir, "prefix_1.ext"); + final File alternative2 = new File(testDir, "prefix_2.ext"); + + public void testGetUniqueNamedFile() throws IOException { + FileUtils.deleteDirectory(testDir); + testDir.mkdirs(); + try { + assertThat(FileUtils.getUniqueNamedFile(baseFile)).isEqualTo(baseFile); + baseFile.createNewFile(); + assertThat(FileUtils.getUniqueNamedFile(baseFile)).isEqualTo(alternative1); + alternative1.createNewFile(); + assertThat(FileUtils.getUniqueNamedFile(baseFile)).isEqualTo(alternative2); + assertThat(FileUtils.getUniqueNamedFile(baseFile)).isEqualTo(alternative2); + } finally { + FileUtils.deleteDirectory(testDir); + } + } + + public static void testFileUrl() { + assertThat(FileUtils.isFileUrl("file:///tmp/foo/bar")).isTrue(); + assertThat(FileUtils.isFileUrl("http://www.google.com")).isFalse(); + assertThat(FileUtils.fileToUrl(new File("/tmp/foo/bar"))).isEqualTo("file:///tmp/foo/bar"); + assertThat(FileUtils.urlToFile("file:///tmp/foo/bar").getPath()).isEqualTo("/tmp/foo/bar"); + } + + public void testCreateRemoveDirectories() { + FileUtils.deleteDirectory(testDir); + assertThat(testDir.exists()).isFalse(); + FileUtils.mkdirs(testDir); + assertThat(testDir.exists()).isTrue(); + FileUtils.deleteDirectory(testDir); + assertThat(testDir.exists()).isFalse(); + } +} diff --git a/tests/src/cgeo/geocaching/utils/HtmlUtilsTest.java b/tests/src/cgeo/geocaching/utils/HtmlUtilsTest.java index 65e86b8..e75c2e6 100644 --- a/tests/src/cgeo/geocaching/utils/HtmlUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/HtmlUtilsTest.java @@ -15,4 +15,9 @@ public class HtmlUtilsTest extends TestCase { assertThat(HtmlUtils.extractText("<b>bold</b>")).isEqualTo("bold"); } + public static void testRemoveExtraParagraph() { + assertThat(HtmlUtils.removeExtraParagraph("<p></p>")).isEqualTo(""); + assertThat(HtmlUtils.removeExtraParagraph("<p>Test</p>")).isEqualTo("Test"); + assertThat(HtmlUtils.removeExtraParagraph("<p>1</p><p>2</p>")).isEqualTo("<p>1</p><p>2</p>"); + } } diff --git a/tests/src/cgeo/geocaching/ImageUtilsTest.java b/tests/src/cgeo/geocaching/utils/ImageUtilsTest.java index 7f6c7e5..59253c5 100644 --- a/tests/src/cgeo/geocaching/ImageUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/ImageUtilsTest.java @@ -1,10 +1,9 @@ -package cgeo.geocaching; +package cgeo.geocaching.utils; import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.test.AbstractResourceInstrumentationTestCase; import cgeo.geocaching.test.R; -import cgeo.geocaching.utils.ImageUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java b/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java index 2c6ed18..b442c8a 100644 --- a/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/ProcessUtilsTest.java @@ -6,7 +6,7 @@ import junit.framework.TestCase; public class ProcessUtilsTest extends TestCase { public static void testIsInstalled() { - assertThat(ProcessUtils.isInstalled("com.android.launcher")).isTrue(); + assertThat(ProcessUtils.isInstalled("com.android.settings")).isTrue(); } public static void testIsInstalledNotLaunchable() { @@ -16,7 +16,7 @@ public class ProcessUtilsTest extends TestCase { } public static void testIsLaunchable() { - assertThat(ProcessUtils.isInstalled("com.android.settings")).isTrue(); + assertThat(ProcessUtils.isLaunchable("com.android.settings")).isTrue(); } } diff --git a/tests/src/cgeo/geocaching/utils/RxUtilsTest.java b/tests/src/cgeo/geocaching/utils/RxUtilsTest.java new file mode 100644 index 0000000..cc8589b --- /dev/null +++ b/tests/src/cgeo/geocaching/utils/RxUtilsTest.java @@ -0,0 +1,44 @@ +package cgeo.geocaching.utils; + +import static org.assertj.core.api.Assertions.assertThat; + +import rx.Observable; +import rx.Subscription; +import rx.subjects.PublishSubject; +import rx.subjects.ReplaySubject; + +import android.test.AndroidTestCase; + +public class RxUtilsTest extends AndroidTestCase { + + // Observable.range(int, int) is not kept in the application by proguard. Use an explicit range here. + private static final ReplaySubject<Integer> range = ReplaySubject.createWithSize(10); + static { + for (int i = 1; i <= 10; i++) { + range.onNext(i); + } + range.onCompleted(); + } + + public static void testRememberLast() { + final PublishSubject<String> rawObservable = PublishSubject.create(); + final Observable<String> observable = RxUtils.rememberLast(rawObservable, "initial"); + + // Check that the initial value is present, and is kept there + assertThat(observable.toBlocking().first()).isEqualTo("initial"); + assertThat(observable.toBlocking().first()).isEqualTo("initial"); + + // Check that if the observable is not subscribed, changes are not propagated (similar to not keeping the + // inner subscription active). + rawObservable.onNext("without subscribers"); + assertThat(observable.toBlocking().first()).isEqualTo("initial"); + + // Check that new values are propagated and cached + final Subscription subscription = observable.subscribe(); + rawObservable.onNext("first"); + assertThat(observable.toBlocking().first()).isEqualTo("first"); + subscription.unsubscribe(); + assertThat(observable.toBlocking().first()).isEqualTo("first"); + } + +} diff --git a/tests/src/cgeo/geocaching/utils/TextUtilsTest.java b/tests/src/cgeo/geocaching/utils/TextUtilsTest.java index 29c4864..6c6b82d 100644 --- a/tests/src/cgeo/geocaching/utils/TextUtilsTest.java +++ b/tests/src/cgeo/geocaching/utils/TextUtilsTest.java @@ -14,7 +14,6 @@ public class TextUtilsTest extends AndroidTestCase { public static void testRegEx() { final String page = MockedCache.readCachePage("GC2CJPF"); assertThat(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")).isEqualTo(GCConstantsTest.MOCK_LOGIN_NAME); - assertThat(page.contains("id=\"ctl00_hlRenew\"") || GCConstants.MEMBER_STATUS_PM.equals(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, "???"))).isTrue(); } public static void testReplaceWhitespaces() { @@ -26,4 +25,11 @@ public class TextUtilsTest extends AndroidTestCase { assertThat(TextUtils.getMatch("some" + "\u001C" + "control" + (char) 0x1D + "characters removed", patternAll, "")).isEqualTo("some control characters removed"); assertThat(TextUtils.getMatch("newline\nalso\nremoved", patternAll, "")).isEqualTo("newline also removed"); } + + public static void testGetMatch() { + final Pattern patternAll = Pattern.compile("foo(...)"); + final String text = "abc-foobar-def-fooxyz-ghi-foobaz-jkl"; + assertThat(TextUtils.getMatch(text, patternAll, false, 1, null, false)).isEqualTo("bar"); + assertThat(TextUtils.getMatch(text, patternAll, false, 1, null, true)).isEqualTo("baz"); + } } diff --git a/tests/src/cgeo/junit/CgeoTestRunner.java b/tests/src/cgeo/junit/CgeoTestRunner.java new file mode 100644 index 0000000..94803cf --- /dev/null +++ b/tests/src/cgeo/junit/CgeoTestRunner.java @@ -0,0 +1,125 @@ +package cgeo.junit; + +import com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner; +import com.zutubi.android.junitreport.JUnitReportListener; +import com.zutubi.android.junitreport.JUnitReportTestRunner; + +import android.os.Bundle; +import android.test.AndroidTestRunner; +import android.util.Log; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Test runner which derives from the newer Google instrumentation test runner used by the Espresso test framework. It + * adds junit report functionality by cloning the behavior of the {@link JUnitReportTestRunner}. + * + */ +public class CgeoTestRunner extends GoogleInstrumentationTestRunner { + + /** + * Name of the report file(s) to write, may contain __suite__ in multiFile mode. + */ + private static final String ARG_REPORT_FILE = "reportFile"; + /** + * If specified, path of the directory to write report files to. May start with __external__. + * If not set files are written to the internal storage directory of the app under test. + */ + private static final String ARG_REPORT_DIR = "reportDir"; + /** + * If true, stack traces in the report will be filtered to remove common noise (e.g. framework + * methods). + */ + private static final String ARG_FILTER_TRACES = "filterTraces"; + /** + * If true, produce a separate file for each test suite. By default a single report is created + * for all suites. + */ + private static final String ARG_MULTI_FILE = "multiFile"; + /** + * Default name of the single report file. + */ + private static final String DEFAULT_SINGLE_REPORT_FILE = "junit-report.xml"; + /** + * Default name pattern for multiple report files. + */ + private static final String DEFAULT_MULTI_REPORT_FILE = "junit-report-" + JUnitReportListener.TOKEN_SUITE + ".xml"; + + private static final String LOG_TAG = CgeoTestRunner.class.getSimpleName(); + + private JUnitReportListener mListener; + private String mReportFile; + private String mReportDir; + private boolean mFilterTraces = true; + private boolean mMultiFile = false; + + @Override + public void onCreate(Bundle arguments) { + if (arguments != null) { + Log.i(LOG_TAG, "Created with arguments: " + arguments.keySet()); + mReportFile = arguments.getString(ARG_REPORT_FILE); + mReportDir = arguments.getString(ARG_REPORT_DIR); + mFilterTraces = getBooleanArgument(arguments, ARG_FILTER_TRACES, true); + mMultiFile = getBooleanArgument(arguments, ARG_MULTI_FILE, false); + } else { + Log.i(LOG_TAG, "No arguments provided"); + } + + if (mReportFile == null) { + mReportFile = mMultiFile ? DEFAULT_MULTI_REPORT_FILE : DEFAULT_SINGLE_REPORT_FILE; + } + Log.i(LOG_TAG, "report directory '" + mReportDir + "'"); + Log.i(LOG_TAG, "report file '" + mReportFile + "'"); + + super.onCreate(arguments); + } + + private static boolean getBooleanArgument(Bundle arguments, String name, boolean defaultValue) { + String value = arguments.getString(name); + if (value == null) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + @Override + public void start() { + makeAndroidTestRunnerAccessible(); + super.start(); + } + + private void makeAndroidTestRunnerAccessible() { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + mListener = new JUnitReportListener(getContext(), getTargetContext(), mReportFile, mReportDir, mFilterTraces, mMultiFile); + try { + Class<?> c = getClass(); + Field bridgeTestRunner = c.getSuperclass().getDeclaredField("bridgeTestRunner"); + bridgeTestRunner.setAccessible(true); + Object obj = bridgeTestRunner.get(this); + Method m = obj.getClass().getDeclaredMethod("getAndroidTestRunner", (Class[]) null); + AndroidTestRunner androidTestRunner = (AndroidTestRunner) m.invoke(obj); + androidTestRunner.addTestListener(mListener); + } catch (NoSuchFieldException | InvocationTargetException | IllegalAccessException + | NoSuchMethodException | SecurityException x) { + Log.e(LOG_TAG, x.toString()); + } + return null; + } + }); + } + + @Override + public void finish(int resultCode, Bundle results) { + if (mListener != null) { + mListener.close(); + } + + super.finish(resultCode, results); + } +} diff --git a/tests/src/cgeo/test/Compare.java b/tests/src/cgeo/test/Compare.java index cabbf43..788a191 100644 --- a/tests/src/cgeo/test/Compare.java +++ b/tests/src/cgeo/test/Compare.java @@ -3,7 +3,6 @@ package cgeo.test; import static org.assertj.core.api.Assertions.assertThat; import cgeo.geocaching.Geocache; -import cgeo.geocaching.ICache; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.utils.CryptUtils; @@ -13,7 +12,7 @@ import java.util.Date; public abstract class Compare { - public static void assertCompareCaches(ICache expected, Geocache actual, boolean all) { + public static void assertCompareCaches(final Geocache expected, final Geocache actual, final boolean all) { final String geocode = expected.getGeocode(); final String cacheStr = "Cache " + geocode + ": "; assertThat(actual).isNotNull(); @@ -31,7 +30,7 @@ public abstract class Compare { final Date hiddenDate = actual.getHiddenDate(); assertThat(hiddenDate).isNotNull(); assert hiddenDate != null; // silence the eclipse compiler in the next line - assertThat(hiddenDate.toString()).as(cacheStr + "hidden date").isEqualTo(expected.getHiddenDate().toString()); + assertThat(hiddenDate).as(cacheStr + " hidden date").isEqualTo(expected.getHiddenDate()); assertThat(actual.isPremiumMembersOnly()).as(cacheStr + "premium only").isEqualTo(expected.isPremiumMembersOnly()); if (all) { @@ -48,18 +47,18 @@ public abstract class Compare { assertThat(actual.isFavorite()).as(cacheStr + "favorite status").isEqualTo(expected.isFavorite()); assertThat(actual.isOnWatchlist()).as(cacheStr + "watchlist status").isEqualTo(expected.isOnWatchlist()); - for (String attribute : expected.getAttributes()) { + for (final String attribute : expected.getAttributes()) { assertThat(actual.getAttributes()).as("attributes of " + actual.getGeocode()).contains(attribute); } - for (LogType logType : expected.getLogCounts().keySet()) { + for (final LogType logType : expected.getLogCounts().keySet()) { assertThat(actual.getLogCounts().get(logType)).as("logcount of " + geocode + " for type " + logType.toString()).isGreaterThanOrEqualTo(expected.getLogCounts().get(logType)); } // The inventories can differ too often, therefore we don't compare them. Also, the personal note // cannot be expected to match with different tester accounts. - final int actualSpoilersSize = null != actual.getSpoilers() ? actual.getSpoilers().size() : 0; - final int expectedSpoilersSize = null != expected.getSpoilers() ? expected.getSpoilers().size() : 0; + final int actualSpoilersSize = actual.getSpoilers().size(); + final int expectedSpoilersSize = expected.getSpoilers().size(); assertThat(actualSpoilersSize).as(cacheStr + "spoiler count").isEqualTo(expectedSpoilersSize); } } diff --git a/tests/tests.iml b/tests/tests.iml index 6a6c905..fc811c4 100644 --- a/tests/tests.iml +++ b/tests/tests.iml @@ -4,6 +4,7 @@ <facet type="android" name="Android"> <configuration> <option name="PACK_TEST_CODE" value="true" /> + <option name="UPDATE_PROPERTY_FILES" value="false" /> <includeAssetsFromLibraries>true</includeAssetsFromLibraries> </configuration> </facet> @@ -15,7 +16,7 @@ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" /> </content> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="cgeo" exported="" scope="TEST" /> + <orderEntry type="module" module-name="cgeo" scope="TEST" /> <orderEntry type="module-library"> <library> <CLASSES> @@ -30,17 +31,204 @@ </library> </orderEntry> <orderEntry type="inheritedJdk" /> - <orderEntry type="module-library" scope="PROVIDED"> - <library> - <CLASSES> - <root url="jar://$MODULE_DIR$/../main/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES> - <root url="jar://$MODULE_DIR$/../main/compile-libs/org.eclipse.jdt.annotation_1.1.0.v20130513-1648.jar!/src" /> - </SOURCES> - </library> - </orderEntry> </component> -</module> - + <component name="org.twodividedbyzero.idea.findbugs"> + <option name="_basePreferences"> + <map> + <entry key="property.analysisEffortLevel" value="default" /> + <entry key="property.analyzeAfterCompile" value="false" /> + <entry key="property.annotationGutterIconEnabled" value="true" /> + <entry key="property.annotationSuppressWarningsClass" value="edu.umd.cs.findbugs.annotations.SuppressFBWarnings" /> + <entry key="property.annotationTextRangeMarkupEnabled" value="true" /> + <entry key="property.exportAsHtml" value="true" /> + <entry key="property.exportAsXml" value="true" /> + <entry key="property.exportBaseDir" value="" /> + <entry key="property.exportCreateArchiveDir" value="false" /> + <entry key="property.exportOpenBrowser" value="true" /> + <entry key="property.minPriorityToReport" value="Medium" /> + <entry key="property.runAnalysisInBackground" value="false" /> + <entry key="property.showHiddenDetectors" value="false" /> + <entry key="property.toolWindowToFront" value="true" /> + </map> + </option> + <option name="_detectors"> + <map> + <entry key="AppendingToAnObjectOutputStream" value="true" /> + <entry key="AtomicityProblem" value="true" /> + <entry key="BadAppletConstructor" value="false" /> + <entry key="BadResultSetAccess" value="true" /> + <entry key="BadSyntaxForRegularExpression" value="true" /> + <entry key="BadUseOfReturnValue" value="true" /> + <entry key="BadlyOverriddenAdapter" value="true" /> + <entry key="BooleanReturnNull" value="true" /> + <entry key="BuildInterproceduralCallGraph" value="false" /> + <entry key="BuildObligationPolicyDatabase" value="true" /> + <entry key="BuildStringPassthruGraph" value="true" /> + <entry key="CallToUnsupportedMethod" value="false" /> + <entry key="CalledMethods" value="true" /> + <entry key="CheckCalls" value="false" /> + <entry key="CheckExpectedWarnings" value="false" /> + <entry key="CheckImmutableAnnotation" value="true" /> + <entry key="CheckRelaxingNullnessAnnotation" value="true" /> + <entry key="CheckTypeQualifiers" value="true" /> + <entry key="CloneIdiom" value="true" /> + <entry key="ComparatorIdiom" value="true" /> + <entry key="ConfusedInheritance" value="true" /> + <entry key="ConfusionBetweenInheritedAndOuterMethod" value="true" /> + <entry key="CrossSiteScripting" value="true" /> + <entry key="DefaultEncodingDetector" value="true" /> + <entry key="DoInsideDoPrivileged" value="true" /> + <entry key="DontCatchIllegalMonitorStateException" value="true" /> + <entry key="DontIgnoreResultOfPutIfAbsent" value="true" /> + <entry key="DontUseEnum" value="true" /> + <entry key="DroppedException" value="true" /> + <entry key="DumbMethodInvocations" value="true" /> + <entry key="DumbMethods" value="true" /> + <entry key="DuplicateBranches" value="true" /> + <entry key="EmptyZipFileEntry" value="false" /> + <entry key="EqualsOperandShouldHaveClassCompatibleWithThis" value="true" /> + <entry key="ExplicitSerialization" value="true" /> + <entry key="FieldItemSummary" value="true" /> + <entry key="FinalizerNullsFields" value="true" /> + <entry key="FindBadCast2" value="true" /> + <entry key="FindBadForLoop" value="true" /> + <entry key="FindBugsSummaryStats" value="true" /> + <entry key="FindCircularDependencies" value="false" /> + <entry key="FindDeadLocalStores" value="true" /> + <entry key="FindDoubleCheck" value="true" /> + <entry key="FindEmptySynchronizedBlock" value="true" /> + <entry key="FindFieldSelfAssignment" value="true" /> + <entry key="FindFinalizeInvocations" value="true" /> + <entry key="FindFloatEquality" value="true" /> + <entry key="FindFloatMath" value="false" /> + <entry key="FindHEmismatch" value="true" /> + <entry key="FindInconsistentSync2" value="true" /> + <entry key="FindJSR166LockMonitorenter" value="true" /> + <entry key="FindLocalSelfAssignment2" value="true" /> + <entry key="FindMaskedFields" value="true" /> + <entry key="FindMismatchedWaitOrNotify" value="true" /> + <entry key="FindNakedNotify" value="true" /> + <entry key="FindNoSideEffectMethods" value="true" /> + <entry key="FindNonSerializableStoreIntoSession" value="false" /> + <entry key="FindNonSerializableValuePassedToWriteObject" value="false" /> + <entry key="FindNonShortCircuit" value="true" /> + <entry key="FindNullDeref" value="true" /> + <entry key="FindNullDerefsInvolvingNonShortCircuitEvaluation" value="true" /> + <entry key="FindOpenStream" value="true" /> + <entry key="FindPuzzlers" value="true" /> + <entry key="FindRefComparison" value="true" /> + <entry key="FindReturnRef" value="true" /> + <entry key="FindRoughConstants" value="true" /> + <entry key="FindRunInvocations" value="true" /> + <entry key="FindSelfComparison" value="true" /> + <entry key="FindSelfComparison2" value="true" /> + <entry key="FindSleepWithLockHeld" value="true" /> + <entry key="FindSpinLoop" value="true" /> + <entry key="FindSqlInjection" value="true" /> + <entry key="FindTwoLockWait" value="true" /> + <entry key="FindUncalledPrivateMethods" value="true" /> + <entry key="FindUnconditionalWait" value="true" /> + <entry key="FindUninitializedGet" value="true" /> + <entry key="FindUnrelatedTypesInGenericContainer" value="true" /> + <entry key="FindUnreleasedLock" value="true" /> + <entry key="FindUnsatisfiedObligation" value="true" /> + <entry key="FindUnsyncGet" value="true" /> + <entry key="FindUseOfNonSerializableValue" value="true" /> + <entry key="FindUselessControlFlow" value="true" /> + <entry key="FormatStringChecker" value="true" /> + <entry key="FunctionsThatMightBeMistakenForProcedures" value="true" /> + <entry key="HugeSharedStringConstants" value="true" /> + <entry key="IDivResultCastToDouble" value="true" /> + <entry key="IncompatMask" value="true" /> + <entry key="InconsistentAnnotations" value="true" /> + <entry key="InefficientIndexOf" value="true" /> + <entry key="InefficientInitializationInsideLoop" value="true" /> + <entry key="InefficientMemberAccess" value="false" /> + <entry key="InefficientToArray" value="true" /> + <entry key="InfiniteLoop" value="true" /> + <entry key="InfiniteRecursiveLoop" value="true" /> + <entry key="InheritanceUnsafeGetResource" value="true" /> + <entry key="InitializationChain" value="true" /> + <entry key="InitializeNonnullFieldsInConstructor" value="true" /> + <entry key="InstantiateStaticClass" value="true" /> + <entry key="IntCast2LongAsInstant" value="true" /> + <entry key="InvalidJUnitTest" value="true" /> + <entry key="IteratorIdioms" value="true" /> + <entry key="LazyInit" value="true" /> + <entry key="LoadOfKnownNullValue" value="true" /> + <entry key="LostLoggerDueToWeakReference" value="true" /> + <entry key="MethodReturnCheck" value="true" /> + <entry key="Methods" value="true" /> + <entry key="MultithreadedInstanceAccess" value="true" /> + <entry key="MutableLock" value="true" /> + <entry key="MutableStaticFields" value="true" /> + <entry key="Naming" value="true" /> + <entry key="Noise" value="false" /> + <entry key="NoiseNullDeref" value="false" /> + <entry key="NoteAnnotationRetention" value="true" /> + <entry key="NoteCheckReturnValueAnnotations" value="true" /> + <entry key="NoteDirectlyRelevantTypeQualifiers" value="true" /> + <entry key="NoteJCIPAnnotation" value="true" /> + <entry key="NoteNonNullAnnotations" value="false" /> + <entry key="NoteNonnullReturnValues" value="false" /> + <entry key="NoteSuppressedWarnings" value="true" /> + <entry key="NoteUnconditionalParamDerefs" value="true" /> + <entry key="NumberConstructor" value="true" /> + <entry key="OptionalReturnNull" value="true" /> + <entry key="OverridingEqualsNotSymmetrical" value="true" /> + <entry key="PreferZeroLengthArrays" value="true" /> + <entry key="PublicSemaphores" value="false" /> + <entry key="QuestionableBooleanAssignment" value="true" /> + <entry key="ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass" value="true" /> + <entry key="ReadReturnShouldBeChecked" value="true" /> + <entry key="RedundantInterfaces" value="true" /> + <entry key="ReflectiveClasses" value="true" /> + <entry key="RepeatedConditionals" value="true" /> + <entry key="ResolveAllReferences" value="false" /> + <entry key="RuntimeExceptionCapture" value="true" /> + <entry key="SerializableIdiom" value="true" /> + <entry key="StartInConstructor" value="true" /> + <entry key="StaticCalendarDetector" value="true" /> + <entry key="StringConcatenation" value="true" /> + <entry key="SuperfluousInstanceOf" value="true" /> + <entry key="SuspiciousThreadInterrupted" value="true" /> + <entry key="SwitchFallthrough" value="true" /> + <entry key="SynchronizationOnSharedBuiltinConstant" value="true" /> + <entry key="SynchronizeAndNullCheckField" value="true" /> + <entry key="SynchronizeOnClassLiteralNotGetClass" value="true" /> + <entry key="SynchronizingOnContentsOfFieldToProtectField" value="true" /> + <entry key="TestASM" value="false" /> + <entry key="TestDataflowAnalysis" value="false" /> + <entry key="TestingGround" value="false" /> + <entry key="TestingGround2" value="false" /> + <entry key="TrainFieldStoreTypes" value="true" /> + <entry key="TrainLongInstantfParams" value="true" /> + <entry key="TrainNonNullAnnotations" value="true" /> + <entry key="TrainUnconditionalDerefParams" value="true" /> + <entry key="URLProblems" value="true" /> + <entry key="UncallableMethodOfAnonymousClass" value="true" /> + <entry key="UnnecessaryMath" value="true" /> + <entry key="UnreadFields" value="true" /> + <entry key="UselessSubclassMethod" value="false" /> + <entry key="VarArgsProblems" value="true" /> + <entry key="VolatileUsage" value="true" /> + <entry key="WaitInLoop" value="true" /> + <entry key="WrongMapIterator" value="true" /> + <entry key="XMLFactoryBypass" value="true" /> + </map> + </option> + <option name="_reportCategories"> + <map> + <entry key="BAD_PRACTICE" value="true" /> + <entry key="CORRECTNESS" value="true" /> + <entry key="EXPERIMENTAL" value="true" /> + <entry key="I18N" value="true" /> + <entry key="MALICIOUS_CODE" value="true" /> + <entry key="MT_CORRECTNESS" value="true" /> + <entry key="PERFORMANCE" value="true" /> + <entry key="SECURITY" value="true" /> + <entry key="STYLE" value="true" /> + </map> + </option> + </component> +</module>
\ No newline at end of file |